This is a simple IBC enabled CosmWasm smart contract. It expects to be deployed on two chains and, when prompted, will send messages to its counterpart. It then counts the number of times messages have been received on both sides.
At a high level, to use this contract:
Increment {}
method on one contract to increment the
send a message and increment the count on the other one.GetCount { connection }
query to determine the message
count for a given connection.This repo also contains a demo contract which makes an infinite loop
of contract calls over IBC. See the README on the
zeke/ibc-replay
branch for more information and an integration test that demonstrates
this.
To connect two CosmWasm contracts over IBC you must establish an IBC channel between them. The IBC channel establishment process uses a four way handshake. Here is a summary of the steps:
OpenInit
Hello chain B, here is information that you can use to
verify I am chain A. Do you have information I can use?OpenTry
Hello chain A, I have verified that you are who you say
you are. Here is my verification information.OpenAck
Hello chain B. Thank you for that information I have
verified you are who you say you are. I am now ready to talk.OpenConfirm
Hello chain A. I am also now ready to talk.Once the handshake has been completed a channel will be established
that the ibc messages may be sent over. In order to do a handshake and
receive IBC messages your contract must implement the following entry
points (see src/ibc.rs
):
ibc_channel_open
- Handles the OpenInit
and OpenTry
handshake
steps.ibc_channel_connect
- Handles the OpenAck
and OpenConfirm
handshake steps.ibc_channel_close
- Handles the closing of an IBC channel by the
counterparty.ibc_packet_receive
- Handles receiving IBC packets from the
counterparty.ibc_packet_ack
- Handles ACK messages from the countarparty. This
is effectively identical to the ACK message type in
TCP.ibc_packet_timeout
- Handles packet timeouts.Having implemented these methods, once you instantiate an instance of the contract it will be assigned a port. Ports identify a receiver on a blockchain in much the same way as ports identify applications on a computer.
You can find the port that has been assigned to your contract by
running junod query wasm contract <ADDRESS>
and inspecting the
ibc_port_id
field. For example:
$ junod query wasm contract juno1r8k4hf7umksu9w53u4sz0jsla5478am6yxr0mhkuvp00yvtmxexsj8wazt
address: juno1r8k4hf7umksu9w53u4sz0jsla5478am6yxr0mhkuvp00yvtmxexsj8wazt
contract_info:
admin: ""
code_id: "1377"
created: null
creator: juno1m7a7nva00p82xr0tssye052r8sxsxvcy2v5qz6
extension: null
ibc_port_id: wasm.juno1r8k4hf7umksu9w53u4sz0jsla5478am6yxr0mhkuvp00yvtmxexsj8wazt
label: ekez-cw-ibc-example
To establish a connecton between two contracts you will need to set up a relayer. If you chose to use hermes, after configuration the command to establish a connection is:
hermes create channel --a-chain uni-3 --b-chain juno-1 --a-port wasm.juno1r8k4hf7umksu9w53u4sz0jsla5478am6yxr0mhkuvp00yvtmxexsj8wazt --b-port wasm.juno1fsay0zux2vkyrsqpepd08q2vlytrfu7gsqnapsfl9ge8mp6fvx3qf062q9 --channel-version counter-1
Then, to start the relayer:
hermes start
Note that you will need to configure hermes for the chains you are relaying between before these commands may be run.
Once the relayer is running, make note of the channel ID that has been established. You will use this when telling the contract to send packets. This is needed because one contract may be connected to multiple channels. You can not assume that your channel is the only one connected at a given time.
For example, to increment the count on the counterparty chain over a connection between local channel-72 and remote channel-90:
junod tx wasm execute juno1r8k4hf7umksu9w53u4sz0jsla5478am6yxr0mhkuvp00yvtmxexsj8wazt '{"increment": { "channel": "channel-72" }}' --from ekez --gas auto --gas-adjustment 2 --fees 12000ujunox
Then, switching to the other chain, we can query that count by running:
junod query wasm contract-state smart juno1fsay0zux2vkyrsqpepd08q2vlytrfu7gsqnapsfl9ge8mp6fvx3qf062q9 '{"get_count": {"channel": "channel-90"}}'
Hermes has started
before sending packets.To run IBC tests (you will need just installed):
just simtest
This contract uses the Cosmos SDK's
simulator to test
IBC interactions between chains. Testing code and information about
its setup can be found in the tests
subdirectory.