ICS20: Fungible Token Transfer

ICS20: Fungible Token Transfer

The ICS20 (opens in a new tab) protocol defines a standard for transferring fungible tokens between two chains using IBC. It is one of the most widely used IBC protocols and is supported by pretty much all chains in the Cosmos.

To initiate an ICS20 transfer from inside a contract, you need to attach an IbcMsg::Transfer message to your contract response like this:

// construct the transfer message
let msg = IbcMsg::Transfer {
    channel_id: "channel-0".to_string(),
    to_address: "cosmos1exampleaddress".to_string(),
    amount: Coin::new(123u128, "ucoin"),
    timeout: env.block.time.plus_seconds(60).into(),
    memo: None,
};
 
// attach the message and return the response
Ok(Response::new().add_message(msg))

Sending this message causes an IBC transfer of the given amount from your contract to the destination chain at the other end of the given channel.

The channel_id is the identifier of the channel you want to use for the transfer. Which channel that should be depends on the source and destination chain. You can find out the correct channel ID using a block explorer (opens in a new tab).

The to_address is the address on the destination chain that should receive the tokens.

The amount is the number and denomination of tokens to send. On the destination chain, the same amount will be received, but the denomination will be of the form ibc/HASH, where HASH is a SHA256 hash uniquely identifying the channel and the source chain denomination. To learn more about this, take a look at the Cosmos Developer Portal (opens in a new tab).

The timeout can either be a timestamp or a block height, as measured on the destination chain. It is used to prevent the transfer from being stuck in limbo if the destination chain does not receive the packet.

The memo is an optional field that can be used to attach a message to the transfer. It is often used for additional functionality like packet-forward-middleware (opens in a new tab) or IBC Callbacks.