CosmWasm/Sylvia counting contract w/ IBC enabled (Cosmos, Rust, CosmWasm, Sylvia)

Overview

CosmWasm/Sylvia counting contract w/ IBC enabled (Cosmos, Rust, CosmWasm, Sylvia)

This repository contains counting contract created during the study of CosmWasm/Sylvia and IBC based contracts development for Cosmos blockchains written using Rust.

The IBC implementation attempt on Sylvia is based on https://github.com/0xekez/cw-ibc-example as at the time of writing this the https://cosmwasm.github.io/sylvia-book/ibc.html#ibc section is empty. Moreover Sylvia does NOT support natively IBC, see maintainer comment CosmWasm/sylvia#19 (comment).

Preface

Rust library skeleton generated using:

cargo new --lib ./counting-contract
cd ./counting-contract
cargo check

Prerequisites

Besides regular dependencies like Go, Rust and CosmWasm binaries, we need additional software to deploy and operate the contracts...

As the IBC relayer is used https://hermes.informal.systems.

cargo install ibc-relayer-cli --bin hermes --locked

To deploy and operate the contracts on Juno we need junod (https://docs.junonetwork.io/validators/getting-setup):

git clone https://github.com/CosmosContracts/juno
cd juno
git fetch --all --tags
git checkout v18.0.0-alpha.2
make install

To deploy and operate the contracts on Osmosis we need osmosisd (https://docs.osmosis.zone/cosmwasm/testnet/cosmwasm-deployment#setup-osmosis-testnet):

curl -sL https://get.osmosis.zone/install > i.py && python3 i.py

Choose option #2 (Client Node) and #2 (Testnet) in order. You may run with sudo but don't forget to chown afterwards...

Build

Aliases in .cargo/config

Built contract to artifacts:

// cargo wasm-debug
cargo wasm
cosmwasm-check target/wasm32-unknown-unknown/release/counting_contract.wasm

Generate contract schemas:

cargo schema

Build optimized deployment version (run in repository root!):

docker run --rm -v "$(pwd)":/code \
  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
  cosmwasm/rust-optimizer:0.14.0
cosmwasm-check artifacts/counting_contract.wasm

Unit Testing

cargo test

Deploying (Testnet)

First we need to configure Juno node:

junod config node https://juno-testnet-rpc.polkachu.com:443
junod config chain-id uni-6

You may explore the testnet tools here: https://polkachu.com/testnets/juno

We will create two Juno wallets first:

junod keys add wallet
// wallet address: juno1dkgs7ymhmnnu3c874wyaakh03jn9l3fes52jxg
junod keys add wallet2
// wallet2 address: juno1qqkj8r6hfqh93jq65jermsmq288je7873jmjh5
junod keys add wallet-ibc --output json > .wallet.junod
// wallet-ibc address: juno1hhfw77usyd6t8y9xuj6xlmqq5nkuqyc9vkcsha
// wallet-ibc explorer: https://www.mintscan.io/juno-testnet/address/juno1hhfw77usyd6t8y9xuj6xlmqq5nkuqyc9vkcsha

Latest faucet working is https://faucet.reece.sh/uni-6/{replace-with-your-address} (e.g. https://faucet.reece.sh/uni-6/juno1hhfw77usyd6t8y9xuj6xlmqq5nkuqyc9vkcsha).

May you want to query wallet balances use junod query bank balances juno1dkgs7ymhmnnu3c874wyaakh03jn9l3fes52jxg

...and create two Osmosis wallets:

osmosisd keys add wallet
// wallet address: osmo1kzd8am90ktcye0yrf7p6z5z4lgz3pg6sp9qu6s
osmosisd keys add wallet2
// wallet2 address: osmo1xdk392u7y36s4fe06eu04e6mt7x4kt5793takz
osmosisd keys add wallet-ibc --output json > .wallet.osmosis
// wallet-ibc address: osmo1fywaxmn73dja3kmd5deuv2gf46ktna6f6el3aw
// wallet-ibc explorer: https://testnet.mintscan.io/osmosis-testnet/account/osmo1fywaxmn73dja3kmd5deuv2gf46ktna6f6el3aw

The faucet address is https://faucet.testnet.osmosis.zone

May you want to query wallet balances use osmosisd query bank balances osmo1kzd8am90ktcye0yrf7p6z5z4lgz3pg6sp9qu6s

We will deploy the contract to uni-6 and osmo-test-5 using junod binary.

First we upload the code:

// Chain A
junod tx wasm store artifacts/counting_contract.wasm --chain-id=uni-6 --from wallet -y --gas=auto --gas-adjustment=1.15 --gas-prices="0.025ujunox" -b sync

// Chain B
osmosisd tx wasm store artifacts/counting_contract.wasm --chain-id=osmo-test-5 --from wallet -y --gas=auto --gas-adjustment=1.15 --gas-prices="0.025uosmo" -b sync

To get contract code ID you must query the txhash, e.g.: junod q tx 0C911A8A7790470297CB5A17C2198F2FD5321BCA9DF8B92D62781745EEBD3F37 --output=json and osmosisd q tx 8A8E552A55D24D0068647BEE6B03E04EC069272F341467955E1FABE37720BAFB --output=json

Than we instantiate the contracts on both networks:

// Chain A
CODE_ID_A=3883
junod tx wasm instantiate "$CODE_ID_A" '{"count":0,"admins":[]}' --label "counting-contract" --chain-id=uni-6 -y --from wallet --admin wallet --gas=auto --gas-adjustment=1.15 --gas-prices="0.025ujunox"

// Chain B
CODE_ID_B=5085
osmosisd tx wasm instantiate "$CODE_ID_B" '{"count":0,"admins":[]}' --label "counting-contract" --chain-id=osmo-test-5 -y --from wallet --admin wallet --gas=auto --gas-adjustment=1.15 --gas-prices="0.025uosmo"

To get initiation info you must query the txhash, e.g.: junod q tx BF1862AD34C328A30D0CE99DD684E71E015FB2E95D29D55AD603B24A7324EB14 --output=json and osmosisd q tx 197AC7FA66DA0E5E35EDE2F822F8DC6A54DDD5936D28B7812DC2DC7DE3A41414 --output=json

Now we need to query the instantiated contracts:

// Chain A
CONTRANT_ADDRESS_A=juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0
junod query wasm contract "$CONTRANT_ADDRESS_A"

// Chain B
CONTRANT_ADDRESS_B=osmo1xz00vhlm7e3ysj9f2v3jtcjpqvectwgdkkxuau8rw290ys087s6qtk24hy
osmosisd query wasm contract "$CONTRANT_ADDRESS_B"

Look at ibc_port_id in the output. Should the contract have IBC entry points enabled it will contain a value e.g. wasm.juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0

Before starting the relayer we need to configure it:

mkdir ~/.hermes && touch ~/.hermes/config.toml
cat .hermes.config.toml > ~/.hermes/config.toml
hermes config validate

...and generate wallets for relaying:

hermes keys add --chain uni-6 --key-file .wallet.junod
hermes keys add --chain osmo-test-5 --key-file .wallet.osmosis

May you want to query balances use hermes keys balance --chain osmo-test-5 and hermes keys balance --chain uni-6. .wallet.* contain sensitive data— make sure you keep them in .gitignore!

Afterwards, in order to get IBC running we need to create the relayer channel:

IBC_PORT_A=wasm.juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0
IBC_PORT_B=wasm.osmo1xz00vhlm7e3ysj9f2v3jtcjpqvectwgdkkxuau8rw290ys087s6qtk24hy
hermes create channel --a-chain uni-6 --b-chain osmo-test-5 --a-port "$IBC_PORT_A" --b-port "$IBC_PORT_B" --channel-version counter-contract-1 --new-client-connection

After successfully running hermes create channel you should see smth like:

SUCCESS Channel {
    ordering: Unordered,
    a_side: ChannelSide {
        chain: BaseChainHandle {
            chain_id: ChainId {
                id: "uni-6",
                version: 6,
            },
            runtime_sender: Sender { .. },
        },
        client_id: ClientId(
            "07-tendermint-691",
        ),
        connection_id: ConnectionId(
            "connection-782",
        ),
        port_id: PortId(
            "wasm.juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0",
        ),
        channel_id: Some(
            ChannelId(
                "channel-839",
            ),
        ),
        version: Some(
            Version(
                "counter-contract-1",
            ),
        ),
    },
    b_side: ChannelSide {
        chain: BaseChainHandle {
            chain_id: ChainId {
                id: "osmo-test-5",
                version: 5,
            },
            runtime_sender: Sender { .. },
        },
        client_id: ClientId(
            "07-tendermint-1424",
        ),
        connection_id: ConnectionId(
            "connection-1329",
        ),
        port_id: PortId(
            "wasm.osmo1xz00vhlm7e3ysj9f2v3jtcjpqvectwgdkkxuau8rw290ys087s6qtk24hy",
        ),
        channel_id: Some(
            ChannelId(
                "channel-4347",
            ),
        ),
        version: Some(
            Version(
                "counter-contract-1",
            ),
        ),
    },
    connection_delay: 0ns,
}

Before starting the channel relayer you need to update ~/.hermes/config.toml and add proper channel list (see create channel command output— to allow created channels):

// UPDATE [[chains]]: list = [["wasm.juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0", "channel-839"], ["wasm.osmo1xz00vhlm7e3ysj9f2v3jtcjpqvectwgdkkxuau8rw290ys087s6qtk24hy", "channel-4347"]]
cat .hermes.config.toml > ~/.hermes/config.toml
hermes config validate
hermes start

Interacting with contracts (Testnet)

Check our counters states on both chains:

// Assuming addresses were set during the steps above...
// CONTRANT_ADDRESS_A=juno1wjjx974u9j80wazvxsx3ukr85jmazk7szk37qn0kmelu98gl620qwxqxz0
// CONTRANT_ADDRESS_B=osmo1xz00vhlm7e3ysj9f2v3jtcjpqvectwgdkkxuau8rw290ys087s6qtk24hy

junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"count": {}}' --chain-id=uni-6
junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"ibc_count": {"channel": "channel-839"}}' --chain-id=uni-6

osmosisd query wasm contract-state smart "$CONTRANT_ADDRESS_B" '{"count": {}}' --chain-id=osmo-test-5
osmosisd query wasm contract-state smart "$CONTRANT_ADDRESS_B" '{"ibc_count": {"channel": "channel-4347"}}' --chain-id=osmo-test-5

Let's try to increment counts directly (on Juno):

junod tx wasm execute "$CONTRANT_ADDRESS_A" '{"increment_count": {}}' --chain-id=uni-6 --from wallet -y --gas=auto --gas-adjustment=1.3 --gas-prices="0.025ujunox" -b sync
// Now query the contract on Juno and check results
junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"count": {}}' --chain-id=uni-6
junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"ibc_count": {"channel": "channel-4347"}}' --chain-id=uni-6

And use IBC called on Osmosis contract (local channel_id=channel-4347) to increment Juno contract count... remotely!:

osmosisd tx wasm execute "$CONTRANT_ADDRESS_B" '{"increment_ibc_count": {"channel": "channel-4347"}}' --chain-id=osmo-test-5 -y --from wallet --gas=auto --gas-adjustment=1.3 --gas-prices="0.025uosmo"
// Now query the contract on Juno and check results
junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"ibc_count": {"channel": "channel-839"}}' --chain-id=uni-6

You might do call increment vice-versa, from Juno using junod tx wasm execute "$CONTRANT_ADDRESS_A" '{"increment_ibc_count": {"channel": "channel-839"}}' --chain-id=uni-6 --from wallet -y --gas=auto --gas-adjustment=1.3 --gas-prices="0.025ujunox" -b sync

...now let's decrease count in Juno contract through Osmosis:

osmosisd tx wasm execute "$CONTRANT_ADDRESS_B" '{"decrement_ibc_count": {"channel": "channel-4347"}}' --chain-id=osmo-test-5 -y --from wallet --gas=auto --gas-adjustment=1.3 --gas-prices="0.025uosmo"
// Now query the contract on Juno and check results
junod query wasm contract-state smart "$CONTRANT_ADDRESS_A" '{"ibc_count": {"channel": "channel-839"}}' --chain-id=uni-6

...after all let's check what happened to Osmosis IBC related states:

osmosisd query wasm contract-state smart "$CONTRANT_ADDRESS_B" '{"ibc_count": {"channel": "channel-4347"}}' --chain-id=osmo-test-5

In case your relayer was not working you might have some ibc_channel_timeouts stored... If not— stop relayer for a while and repeat the steps above; you will see NO increase in counter states on remote contract and ibc_channel_timeouts number increasing with every call to increment_ibc_count or decrement_ibc_count.

You might also like...
A template to build smart contracts in Rust to run inside a Cosmos SDK module on all chains that enable it.

CosmWasm Starter Pack This is a template to build smart contracts in Rust to run inside a Cosmos SDK module on all chains that enable it. To understan

CosmOS - experimental operating system written in Rust.

CosmOS A simple operating system written in Rust. Table of Contents CosmOS Setup QEMU Run OS dev resources General Bootloader Setup Linux Arch pacman

Swap token protocol for cryptocurrencies, supported in cosmos network, such as UST, LUNA, LUNI, etc.

Tokenswap This is a Smart Contract built in Rust to run inside Cosmos SDK module on all chains that enable it. To understand the framework better, ple

Move VM for the Cosmos SDK

NovaVM Move VM for the Cosmos SDK. It allows you to compile, initialize and execute Move smart contracts from Go applications, in particular from x/mo

Twinsies is a specialized reference-counting pointer where the item is jointly owned in 2 places

twinsies Twinsies is a special shared pointer, similar to an Arc, where two specific objects (called [Joint]) share joint ownership of the underlying

A library facilitating the signing and broadcasting of transactions on Cosmos SDK-based blockchains

txf Transaction factory - a library facilitating the signing and broadcasting of transactions (txs) on Cosmos SDK-based blockchains. How to use Exampl

Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana (WIP) ⛏👷🚧⚠️
Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana (WIP) ⛏👷🚧⚠️

Solana BPF Boilerplate Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana This boilerplate provides the following. Si

A Simple Rust NFT API + Smart Contract

Rust NFT API Purpose Rust NFT API is a simple RESTful API developed in Rust that offers functionalities for creating, retrieving, and listing Non-Fung

Examples and helpers to build NFT contracts on CosmWasm

CosmWasm NFTS This repo is the official repository to work on all NFT standard and examples in the CosmWasm ecosystem. cw721 and cw721-base were moved

Owner
Alex Cryp
Lost in Cryptoverse
Alex Cryp
Package used by the cosmos-rust-interface. Makes direct use of cosmos-rust.

Package used by the cosmos-rust-interface. Makes direct use of cosmos-rust (cosmos‑sdk‑proto, osmosis-proto, cosmrs).

Philipp 4 Dec 26, 2022
Cosmwasm in Cosmwasm through ComposableFi/cosmwasm-vm

Cosmwasmception Running Fastest way to run this contract would be through our vm. But note that our vm runs an already built version this contract, so

Abdullah Eryuzlu 3 Oct 5, 2022
Smart Contract built in Rust to run inside Cosmos SDK module on all chains that enable it

CoinSwap is a Smart Contract that is built on the terra blockchain and can be used to swap cryptocurrencies such as LUNA, UST, TerraUSD, Anchor, Mirror Protocol, LUNI and other CW20 tokens. The Project also contains a smart contract which works as a analysis tool for the gas fees on the Terra Blockchain.

Prajjwal Chittori 9 Oct 11, 2022
CosmWasm-Examples is a collection of example contracts and applications built using the CosmWasm framework

CosmWasm-Examples is a collection of example contracts and applications built using the CosmWasm framework. CosmWasm is a secure and efficient smart contract platform designed specifically for the Cosmos ecosystem.

Vitalii Tsyhulov 20 Jun 9, 2023
A simple example demonstrating cross-contract calls in CosmWasm smart contracts

Cross-contract calls This tutorial demonstrates cross-contract calls with CosmWasm v1. Overview An end user calls the reservation contract to register

csli Tools 3 Sep 12, 2022
CosmWasm multi-contract testing framework

Multi Test: Test helpers for multi-contract interactions Warning: Alpha Software Designed for internal use only. This is used for testing cw-plus cont

CosmWasm 7 Dec 6, 2022
Template for multi-contract CosmWasm projects

CosmWasm Template Template for multi-contract CosmWasm projects How to Use Install cargo-make: cargo install --force cargo-make Run formatter: cargo m

null 11 Jan 28, 2023
IBC modules and relayer - Formal specifications and Rust implementation

ibc-rs Rust implementation of the Inter-Blockchain Communication (IBC) protocol. This project comprises primarily four crates: The ibc crate defines t

Informal Systems 296 Dec 31, 2022
Rust implementation of the Inter-Blockchain Communication (IBC) protocol.

ibc-rs Rust implementation of the Inter-Blockchain Communication (IBC) protocol. This project hosts the ibc rust crate which defines the main data str

COSMOS 37 Dec 26, 2022
An all-in-one IBC protocol providing fungible token transfer, interchain account, and async query functionalities

ICS-999 An all-in-one IBC protocol providing fungible token transfer, interchain account (ICA), and query (ICQ) functionalities, implemented in CosmWa

larry 9 Apr 1, 2023