Register Existing Token
If you own an ERC-20 token on a single chain and want a wrapped, bridgeable version on other chains, you can register it as a Canonical Interchain Token using the Interchain Token Factory contract. Each token can only be registered once as a canonical token on its “home chain”.
You can register your existing token directly via the contract or use the ITS Portal no-code solution. Take a look at the diagram below to understand the process of registering an existing token as a Canonical Interchain Token.
💡
This diagram is interactive—click on the function names!
Register Your Token as a Canonical Token Using the Interchain Token Factory
Use the registerCanonicalInterchainToken
function to register your token.
function registerCanonicalInterchainToken( address tokenAddress // address of your token) external payable returns (bytes32 tokenId) {}
This function deploys a Lock/Unlock Token Manager on the source chain, connects it to ITS upon deployment, and returns a unique token ID. Triggering the registerCanonicalInterchainToken()
function initiates the process of registering your custom token with a Lock/Unlock token manager type on your token’s home chain.
Once your token is registered on the home chain, you can call the deployRemoteCanonicalInterchainToken()
function. This will deploy an Interchain Token on a different blockchain that connects to your canonical token on the home chain.
Deploy a Remote Canonical Interchain Token
Use the deployRemoteCanonicalInterchainToken
function to deploy the token on a remote chain as a cross-chain transaction:
function deployRemoteCanonicalInterchainToken( address originalTokenAddress, // original token address string calldata destinationChain, // destination chain name uint256 gasValue // gas value) public payable returns (bytes32 tokenId) {};
This function deploys a token connected to your registered token on the home chain, making it bridgeable to the destination chain, and returns a token ID.
🚨
NOTE: The security of your token is only as strong as the security of the chains with which it integrates. When deploying an interchain token, ensure that all target chains are trustworthy.
Execute Code on Token Receipt
When transferring tokens across chains, you might want to execute specific code when the tokens arrive at their destination. This is possible by implementing the InterchainTokenExecutable
interface in your destination contract.
Implement the InterchainTokenExecutable Interface
Your destination contract should implement the InterchainTokenExecutable interface:
interface InterchainTokenExecutable { function executeWithInterchainToken( bytes32 commandId, string calldata sourceChain, bytes calldata sourceAddress, bytes calldata data, bytes32 tokenId, address token, uint256 amount ) external;}
When tokens are sent to this contract, the executeWithInterchainToken
function will be automatically called with:
amount
: The quantity of tokens transferredtoken
: The address of the token contractdata
: Any additional data you included with the transfer
Example implementation:
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;
import "@axelar-network/interchain-token-service/contracts/executable/InterchainTokenExecutable.sol";
contract MyReceiver is InterchainTokenExecutable { // Event to log token receipts event TokensReceived( string sourceChain, address sender, uint256 amount, bytes32 tokenId );
// This function will be called automatically when tokens are received function executeWithInterchainToken( bytes32 commandId, string calldata sourceChain, bytes calldata sourceAddress, bytes calldata data, bytes32 tokenId, address token, uint256 amount ) external override { // Extract the sender address from sourceAddress address sender = abi.decode(sourceAddress, (address));
// Your execution logic here - for example: // - Process the received payment // - Store transaction information // - Execute business logic based on data parameter
// Emit event for tracking emit TokensReceived(sourceChain, sender, amount, tokenId); }}
Send Tokens with Custom Data
When calling interchainTransfer
, include your custom data in the metadata
parameter using this format:
bytes metadata = bytes.concat(bytes4(0), yourCustomPayload);
Example usage:
// Encode function parameters or any data you want to passbytes memory yourCustomPayload = abi.encode(param1, param2, param3);
// Format metadata properly for executionbytes memory metadata = bytes.concat(bytes4(0), yourCustomPayload);
// Send the interchain transfer with the metadatainterchainTokenService.interchainTransfer( tokenId, destinationChain, destinationAddress, amount, metadata, gasValue);
This will:
- Transfer tokens to the destination contract
- Call
executeWithInterchainToken
on that contract - Pass your custom data in the
data
parameter - Provide the transferred amount in the
amount
parameter
For a full implementation example, see the its-executable example repository.
What’s Next
You can initiate an interchain transfer from your source chain to a destination chain by using the interchainTransfer
method on the ITS contract.
For further examples utilizing the Interchain Token Service, check out the axelar-examples
repository on GitHub. There, you will find an example implementation titled its-canonical-token
, which demonstrates how to deploy canonical Interchain Tokens and perform cross-chain transfers.
Tutorial
For a step-by-step guide on registering an existing token, check out the Programmatically Create a Canonical Interchain Token Using the Interchain Token Service tutorial.