Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The Inter-Blockchain Communication Protocol (IBC) is an open-source protocol to handle authentication and transport of data between blockchains.
Two local secrets can Inter-blockchainly communicate with each other via a Hermes relayer
For deployment of production level relaying services and config/guide information for both RLY and Hermes please refer to --> IBC relayers documentation
In this demo, you will learn how to create two LocalSecret docker containers that can send IBC token transfers to each other using a Hermes relayer. This tutorial assumes that you already have SecretCLI installed on your machine. In order to follow along, clone the Secret-IBC-setup repo before proceeding.
Next, install Hermes relayer. You can use the hermes configuration found in the Secret Labs examples repository for your configuration of Hermes.
If you are using a Mac, you may need to press Command + Shift + .
(the period key) in order to see your Hermes configuration file.
The configuration file can be found in $HOME/.hermes/bin
Make sure you have Docker installed and running. Then, cd
into ./secret-ibc-setup/relayer and run:
This launches two LocalSecret containers:
localsecret-1 on port 26657
localsecret-2 on port 36657
Now let's establish an IBC channel with Hermes between the LocalSecret containers in order to make an IBC token transfer.
If you've never funded a Hermes wallet before, learn how to do so here.
If you would like to do further reading, refer to the LocalSecret wallet docs and the Hermes wallet docs.
To create an IBC transfer channel, make sure both LocalSecret chains are running in Docker, open a new terminal window in your code editor, and then run:
SecretCLI will ask you to confirm the transaction before signing:
Query that the transaction was successful:
You have successfully created an IBC transfer channel on channel-0
🎉.
Next, start Hermes:
Assuming you have the wallet key 'a'
which is not the relayer's key, run:
Query that the transaction was successful:
If you run into the error cannot send packet using client (07-tendermint-0) with status Expired: client is not active
it is because the LocalSecret trusting period is 79 seconds.
To resolve this error you must launch the LocalSecret containers, create the IBC transfer channel, and start Hermes within 79 seconds of each other.
Assuming you did not run into an error, 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:
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.
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
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
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.
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:
should implement the following interface for a sudo message:
A step-by-step guide on how to auto-wrap SNIP-20 tokens with IBC hooks.
In this tutorial, you will learn how to use IBC hooks to auto-wrap SNIP-20 tokens 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!
What You Will Learn: This tutorial is structured to cover the following key steps:
Setting up a Hermes relayer between two LocalSecret chains, specifically Chain secretdev-1 and Chain secretdev-2.
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! 🏊♀️
To follow along with this tutorial, setup a Hermes relayer between two LocalSecret chains using the Secret IBC setup documentation. Once you have established an IBC transfer channel, 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 IBC denom of the token.
Want to learn more about IBC denoms? Read the Cosmos documentation here.
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:
If you have never funded a Hermes wallet or LocalSecret wallet before, learn how to do so here.
If you would like to do further reading, refer to the LocalSecret wallet docs and the Hermes wallet docs.
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, let's upload the SNIP-20 contract and instantiate it with the correct IBC denom. cd
into ./contracts/snip20-reference-impl and then compile the contract:
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 🎉🚀
Now let's upload and instantiate the wasm hooks contractFirst, cd
into ./contracts/ibc-hooks-contract
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.
snip20_address
and snip20_code_hash
: Details of the SNIP-20 token on Secret Network. See Secret (SNIP 20) token contracts list for the exact details for each token.
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.
Secret Network offers verifiable on-chain randomness for the entire Cosmos Ecosystem via IBC.
We have two methods available, depending on whether your chain supports IBC-hooks or not.
In case your chain supports IBC hooks, please take a look here: Secret VRF for IBC with IBC-Hooks
In case your chain does not support IBC hooks, please take a look here:SecretVRF for IBC via proxy contracts
Need assistance using SecretVRF for your dApp with IBC ? Please ask in the Secret Network Telegram or Discord.
Verifiable on-chain random number generator for the entire Cosmos.
This VRF tutorial uses IBC Hooks, as introduced in IBC v3.4.0. If your chain is on a previous IBC version, see the SecretVRF tutorial using proxy contracts here.
Secret VRF is a provably fair and verifiable on-chain random number generator (RNG) that enables smart contracts to access random values without compromising security or usability. Coupled with cross-chain interoperable smart contracts using IBC hooks, Secret Network enables developers and projects across the Cosmos access to state-of-the-art on-chain RNG.
Use Secret VRF to build reliable smart contracts for any application that relies on unpredictable outcomes:
NFT Minting: Utilize randomness for features like unordered minting, trait randomization, and identity numbering, enhancing the authenticity and security of NFT collections.
Web3 Gaming: Apply randomness in gambling, damage calculation, loot boxes, and boss drops to build trust among players by ensuring fairness and preventing any player from having an unfair advantage.
DAO Operations: Employ randomness for wallet initialization, task assigning, unordered voting/liquidations, and order book ordering, facilitating equitable and secure decentralized governance and operations.
Learn more about how SecretVRF works in-depth here.
To use SecretVRF on any IBC-enabled chain with IBC hooks, all that is required is:
An IBC transfer channel between Secret Network and the consumer chain that receives randomness.
Uploading the RNG Consumer Contract to your chain and directing it to your chain's transfer channel
You can look up existing transfer channels between Secret Network on a block explorer such as Ping here.
Git clone
the IBC hooks randomness repository:
Update the SECRET_TRANSFER_CHANNEL_ID
and the CHAIN_TRANSFER_CHANNEL_ID
to the channel-id for your IBC-enabled chain:
For this example, we request randomness on Juno, but you can request randomness on any IBC-compatible chain that has a transfer channel established with Secret Network.
Once you have updated the transfer channels, compile the contract:
Upload the compiled contract:
Upon successful upload, a code_id
is returned:
Instantiate the contract with the returned code_id
:
Upon succesful instantiation, a contract_address
is returned:
Now that you've instantiated your randomness contract, all that's left is to request randomness! Simply execute request_random:
A transaction hash will be returned:
You can update the job_id
string to any string of your choosing
Navigate to the recently received transactions for your contract:
And then view the magic of cross-chain randomness with IBC hooks 😍:
Congrats! You've just sent a verifiable on-chain random byte
with SecretVRF 🙌.
Secret VRF revolutionizes blockchain applications by providing a secure and verifiable source of randomness, critical for fairness in NFT minting, gaming, and DAO operations. Its seamless integration with IBC hooks enables cross-chain interoperability, allowing developers across the Cosmos ecosystem to build more reliable and elegant smart contracts.
If you have any questions, join our discord and a Secret developer will assist you ASAP.
An example of how to use Secret VRF to fetch random numbers via IBC between Secret and Juno testnet
This documentation serves as a demo on how to send cross-chain random numbers from Secret Network testnet to Juno testnet via IBC. The demo repository can be cloned here.
The design system we’ll be using consists of one Secret contract and two Juno contracts:
Secret Proxy Contract: A Secret contract that requests a random number and specifies the callback information for the response.
Juno Proxy Contract: A Juno contract that sends an IBC message to fetch the random number from the Secret Network proxy contract.
Juno Consumer Contract: A Juno contract that consumes the random numbers generated by the Secret proxy contract.
The Secret proxy contract will produce a different, non-predictable number for each request it receives. You can read more about random numbers on Secret Network in the technical specification of this feature.
See here for a diagram of the system architecture:
There are two steps to configuring your environment:
Upload and instantiate the three smart contracts
Configure an IBC relayer to properly relay packets between your chains of choice (for this demo we will use Hermes).
To begin, let's upload and instantiate the Secret Network proxy smart contract with Secret.js. Clone the repository:
then cd
into secret-ibc-rng-template/node:
Run npm i
to install the dependencies:
Then, create a .env
file and add your wallet mnemonic:
Compile the contract:
Open a new terminal window and cd
into secret-ibc-rng-template/proxy:
Run the Makefile compile script:
Then upload + instantiate the contract in secret-ibc-rng-template/node:
Now that we have our Secret proxy contract, let's upload and instantiate the two Juno smart contracts.
You can configure the consumer contracts for any IBC-compatible chain of your choosing. However, for this demo will be uploading and instantiating our contracts on Juno.
Compile Juno Proxy Contract
Open a new terminal window and cd
into secret-ibc-rng-template/consumer-side-proxy:
Run the Makefile compile script:
Compile Juno Consumer Contract
Open a new terminal window and cd
into secret-ibc-rng-template/consumer:
Run the Makefile compile script:
Upload Juno Contracts
Next, upload the compiled wasm
files to Juno testnet using Juno Tools, and be sure to note the respective codeIds:
You should see the transaction result
returned upon successful upload.
If using the CLI, update to junod v16.0. If using js/ts, update CosmJS to 0.31.
To upload the contracts to Juno testnet, you need Juno testnet tokens in your wallet. Visit faucet.reece.sh/uni-6/<your Juno address> to receive testnet tokens
Next, instantiate the Juno proxy contract by running the following in your terminal:
Then, to query that the instantiation was successful and find the contract address, query the returned txHash
with:
You should see the contract_address
variable:
Now, simply repeat the process for the Juno Consumer contract. The only difference is that the instantiation message is slightly modified because it needs to include the other Juno contract_address
that you instantiated as a pointer:
Query the returned txHash:
You should see the contract_address
variable:
Now that you have successfully uploaded and instantiated the three smart contracts, let's configure Hermes Relayer to relay packets between Secret test and Juno testnet.
First, install Hermes and Gaiad manager.
Then, configure Hermes by navigating to the folder .hermes
and opening the config.toml
file.
If you're on a Mac, you may need to press Command + Shift + Period
to see hidden files, such as the .hermes
folder.
To relay packets between Secret Network testnet and Juno testnet, update the config.toml
file with this configuration:
Next, configure Gaiad Manager by navigating to the folder .gm
, and then update the gm.toml file with the configuration seen here.
If you are using Hermes Relayer, make sure your paths are set up correctly in both the config.toml and gm.toml
. See the image below for reference:
Now let's relay packets! 🎉
Now it's time to execute our IBC smart contracts and relay packets between Juno testnet and Secret testnet. If you run into any issues at this step, refer to the hermes docs for guidance, and also ask questions in the Secret Network developer discord chat!
Start Gaiad Manager
Add your Secret and Juno testnet wallets to Hermes:
cd
into examples/secret-ibc-rng-template:
and update the a.mnemonic
file to include your testnet wallet address like so:
Then run the following to add your testnet wallet address to Hermes:
If you run into errors at this step, see the official Hermes docs for adding keys here.
Create clients
Create connections
In place of 07-tendermint-235 and 07-tendermint-468
, use the client IDs returned to you in your terminal.
Upon success, you should see a message like so:
Now that a channel is established, let's create a channel identifier, which links the Juno proxy contract to the Secret proxy contract. Note that the ports listed below are the addresses of the Juno and Secret proxy contracts which we instantiated earlier.
Create channel identifier
After successfully creating a channel identifier, we can relay packets! Let's start Hermes and then execute the Juno consumer contract to send a random network from Secret Network to Juno 🤯
Start Hermes (open a new terminal window and then run the following)
Hermes will scan the chain for all clients, connections and channels. This might take some time, which is normal. If you want to specify which channels it scans, update the hermes config file to include the following at the end of the chain configuration:
After Hermes has started running, execute the Juno consumer contract to return a random number from Secret via IBC:
Then, query the smart contract to see if it returned the random number:
Upon successful execution, a random number will be returned:
Congrats! You now have the tools to implement cross-chain random number generation via IBC. By following these steps, you can facilitate and execute smart contracts and relay packets between Juno and Secret, as well as any other IBC-compatible chain, expanding the possibilities for blockchain interoperability and fostering new avenues for decentralized application development.
If you are brand new to IBC, here is a quick crash course!
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 (which are implemented in our proxy contract):
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 counter-party.
ibc_packet_ack
- Handles ACK messages from the counter-party.
ibc_packet_timeout
- Handles packet timeouts.
Here is a great repo to learn more about IBC fundamentals 🎉