Initiate a contract call with an incoming IBC token transfer using IBC hooks
IBC-Hooks is an IBC middleware that uses incoming ICS-20 token transfers to initiate smart contract calls. This allows for arbitrary data to be passed in along with token transfers. This is useful for a variety of use cases such as cross-chain token swaps, auto-wrapping of SNIP-20 tokens, General Message Passing (GMP) between Secret Network and EVM chains, and much more! The mechanism enabling this is a memo
field on every ICS20 transfer packet as of IBC v3.4.0. Wasm hooks is an IBC middleware that parses an ICS20 transfer, and if the memo
field is of a particular form, it executes a Wasm contract call.
Note that the metadata in the memo
field is not used within ICS-20 itself, but instead, a middleware or custom CosmWasm contract can wrap around the transfer protocol to parse the metadata and execute custom logic based off of it. See more here.
ICS20 is JSON native, so JSON is used for the memo format:
An ICS20 packet is formatted correctly for Wasm hooks if the following all hold:
memo
is not blank
memo
is valid JSON
memo
has at least one key, with value "wasm"
memo["wasm"]
has exactly two entries, "contract"
and "msg"
memo["wasm"]["msg"]
is a valid JSON object
receiver == memo["wasm"]["contract"]
If an ICS20 packet is not directed towards wasmhooks, wasmhooks doesn't do anything. If an ICS20 packet is directed towards wasmhooks, and is formatted incorrectly, then wasmhooks returns an error.
Before Wasm hooks:
Ensure the incoming IBC packet is cryptographically valid
Ensure the incoming IBC packet has not timed out
In Wasm hooks, before packet execution:
Ensure the packet is correctly formatted (as defined above)
Edit the receiver to be the hardcoded IBC module account
In Wasm hooks, after packet execution:
Construct wasm message as defined above
Execute wasm message
If wasm message has error, return ErrAck
Otherwise continue through middleware
The following contract receives funds from IBC, wraps them as SNIP-20 tokens, and then transfers them to the recipient that is specified in the ibc-hooks message:
A contract that sends an IBC transfer may need to listen for the acknowledgment (ack
) of that packet. To allow contracts to listen to ack
of specific packets, we provide Ack callbacks. The sender of an IBC transfer packet may specify a callback in the memo
field of the transfer packet when the ack
of that packet is received.
Only the IBC packet sender can set the callback
For the callback to be processed, the transfer packet's memo
should contain the following in its JSON:
{"ibc_callback": "secret1contractAddr"}
The WASM hooks will keep the mapping from the packet's channel and sequence to the contract in storage. When an ack
is received, it will notify the specified contract via an execute
message.
Interface for receiving the Acks and Timeouts
The contract that awaits the callback should implement the following interface for a sudo message:
For auto-wrapping public IBC tokens into their SNIP-20 tokens, SCRTLabs has created a auto-wrapping contract deployed on mainnet that everyone can use.
The contract info are:
Contract Address: secret198lmmh2fpj3weqhjczptkzl9pxygs23yn6dsev
Contract Hash: a6c421e3a60cf0e17931945b60d229eb4b4fce5f452122f34412cb937375ee27
To make use of the auto-wrapping contract, follow the guide below:
We begin by initializing a new instance of SecretNetworkClient
but with the caviat that this client is doing the transaction on the other IBC chain (e.g. Osmosis, Kujira etc.). This client is configured with several parameters, including the network URL (chainLCD
), a wallet object, the wallet address, and the IBC chains specific chainId
:
The main action is in the transaction creation, specifically with the otherIBCChainSecretjs.tx.ibc.transfer
function. This function is responsible for initiating an IBC transfer from the other IBC chain to Secret Network. Here's a breakdown of the key parameters:
sender
: The address sending the tokens (in this case, the wallet address associated with the secretjs
client).
receiver
: The address of the wrap deposit contract on the destination chain.
source_channel
: The IBC channel ID on the other Chain.
source_port
: Set to "transfer"
, indicating the type of IBC transfer.
token
: The amount and type of token to be transferred, here 123uscrt
.
timeout_timestamp
: A UNIX timestamp indicating when the transaction should expire if not processed.
memo
: A JSON object containing instructions for the wrap deposit contract.
The auto-wrapping feature comes into play in the memo
field of the transaction. This field carries a JSON object that instructs the wrap deposit contract on how to handle the incoming tokens. The instructions include:
wrap_deposit
: Indicates the action to be taken is a deposit wrap.
recipient_address
: The address on the Secret Network where the wrapped token should be sent to.
This auto-wrapping mechanism is a powerful feature of the Secret Network. When the SNIP-20 tokens are transferred via IBC to another chain (like the Secret Network), they are automatically wrapped into a Secret Token (a privacy-preserving token on the Secret Network). This wrapping is done by the wrap deposit contract specified in the memo
field.
Finally, the transaction is broadcasted with specific options like broadcastCheckIntervalMs
and ibcTxsOptions
. The gasLimit
setting is the maximum amount of gas that can be consumed by the transaction.
In summary, this code snippet demonstrates a sophisticated use of the Secret Network's IBC hooks to automatically wrap public IBC tokens into their SNIP-20 tokens. This process enhances the interoperability and privacy features of the tokens when they are transferred across different blockchains.
A step-by-step guide on how to auto-wrap SNIP-20 tokens with IBC hooks.
What You Will Learn: This tutorial is structured to cover the following key steps:
Executing an IBC token transfer between the two aforementioned chains.
Uploading and initializing a SNIP-20 contract on the secretdev-1 chain.
Uploading and initializing a Wasm Hooks wrapper contract on the secretdev-1 chain.
Transferring tokens from secretdev-1 to secretdev-2, and in the process, utilizing IBC hooks to automatically wrap the SNIP-20 tokens.
Let's dive in! 🏊♀️
You can find the IBC denom of your token by executing an IBC token transfer. Assuming you have funded the LocalSecret wallet 'a'
for chain secretdev-1, run the following:
Query that the transaction was successful:
Now switch to the destination network (secretdev-2) and query the bank balance of wallet 'a'
to confirm that the transaction was successful:
Congrats 🎉 You should now see the ibc-denom returned in the transaction query:
Now upload it (but first make sure you are on chain secretdev-1):
Query that the upload was successful:
If the upload was successful it should return:
Lastly, instantiate the contract with your associated IBC denom:
Query successful instantiation:
If the instantiation was successful, it will return:
Upload:
Query successful upload:
Upon successful upload it will return:
Instantiate:
Query successful instantiation:
If the instantiation was successful it will return:
Now all that's left is to make an IBC token transfer and experience the magic of IBC hooks with the token wrapping contract.
First, initialize the variables in your terminal:
Now execute the token transfer!
Query that it was successful:
Here is an excerpt from the transaction query which includes the IBC memo:
Notice that the sender is wallet address 'a'
and the receiver is the SNIP-20 contract address.
Congrats! You've just successfully used IBC hooks to auto-wrap tokens on Secret Network 🎉🚀
snip20_address
and snip20_code_hash
: Details of the SNIP-20 token on Secret Network. See for the exact details for each token.
In this tutorial, you will learn how to use to auto-wrap between two LocalSecret IBC chains. Simply put, you will learn how to IBC transfer tokens from one blockchain to another blockchain, and in doing so, the token transfer will execute a smart contract call that turns the tokens into privacy-preserving tokens, all with a single token transfer!
Setting up a Hermes relayer between two LocalSecret chains, specifically Chain and Chain .
To follow along with this tutorial, setup a Hermes relayer between two LocalSecret chains using the . Once you have established an , you are ready to proceed to the next step.
In order to auto-wrap SNIP-20 tokens over IBC, you must first instantiate a SNIP-20 smart contract on LocalSecret with the of the token.
Want to learn more about IBC denoms? Read the
If you have never funded a Hermes wallet or LocalSecret wallet before, .
If you would like to do further reading, refer to the and the .
Now, let's upload the SNIP-20 contract and instantiate it with the correct IBC denom. cd
into and then compile the contract:
Now let's upload and instantiate the First, cd
into