Interchain Tokens

💡
Interchain Tokens have received a major update as of July 2023 with many new features! Read on to learn about all of the new capabilities and check out the Interchain Portal.

Axelar has several ways to send supported native tokens, but what if you want have your own ERC-20 token available on multiple chains? Axelar can help with Interchain Tokens!

Interchain Tokens are created and managed by our new Interchain Token Service, which allows you to send tokens cross-chain, build your own asset bridges, build asset transfers into your interchain dApp, and take on many other use cases.

Depending on whether or not you have an existing ERC-20 token, there are two main paths available to you.

  1. I want a new Interchain Token
  2. I want to upgrade existing token(s)

New Interchain Tokens

Standardized Tokens

The simplest type of Interchain Token is to create a brand new Standardized ERC-20 that is available on multiple chains.

The first step is to visit the Interchain Portal. Connect your wallet, select a source network where you have funds and choose to deploy a new ERC-20 token. Make sure to choose an initial supply, or choose the advanced option to allow later minting. You can then choose any additional chains for your new token.

Congratulations! You now have an ERC-20 token available on multiple chains. You can interact with your token on any chain identically, as they are all ERC-20 tokens. You can send, transfer, approve, and use all of the methods you are used to. Additionally, each of these tokens is a Standardized Interchain Token and has an interchainTransfer method allowing you to transfer it between blockchains.

function interchainTransfer(
	string calldata destinationChain,
	bytes calldata recipient,
	uint256 amount,
	bytes calldata metadata
) external payable;

Custom Tokens

If you want more features than the standardized token provides, you can create a custom token. You may want a customized token if you want to customize minting policies, ensure ownership or control of the token by a DAO, create rate limits, or build any other custom logic into your token.

You will need to build this token yourself. Make sure your new token implements the IInterchainToken interface so you can offer interchainTransfer and interchainTransferFrom methods directly on your token.

You can try our sample custom token as a starting point. This token self-registers with the Interchain Token Service, and can be deployed to multiple chains.

Once you have designed your token, you can deploy it to multiple chains using a tool such as the Constant Address Deployer to give it the same address everywhere.

Once the token has been deployed on multiple chains, you’ll want to deploy a Mint/Burn Token Manager for each chain. You can do this by calling deployCustomTokenManager on the Interchain Token Service (or deployRemoteCustomTokenManager for remote chains), and then set the distributor on your token to be the new Token Manager. This will give the Token Manager permissions to mint and burn tokens on your behalf as tokens move between chains.

Here is the signature for deployRemoteCanonicalToken.

/**
* @notice Used to deploy remote TokenManagers and standardized tokens for a canonical token. This needs to be
* called from the chain that registered the canonical token, and anyone can call it.
* @param tokenId the tokenId of the canonical token.
* @param destinationChain the name of the chain to deploy the TokenManager and standardized token to.
* @param gasValue the amount of native tokens to be used to pay for gas for the remote deployment.
* At least the amount specified needs to be passed to the call
* @dev `gasValue` exists because this function can be part of a multicall involving multiple functions that could make remote contract calls.
*/
function deployRemoteCanonicalToken(
	bytes32 tokenId, 
	string calldata destinationChain, 
	uint256 gasValue
) public payable notPaused;

Here is an example of deploying your own Token Manager

function deployTokenManager(bytes32 salt) external {
	bytes memory params = service.getParamsMintBurn(address(this).toBytes(), tokenAddress);
	bytes32 tokenId = service.deployCustomTokenManager(salt, TokenManagerType.MINT_BURN, params);
	address tokenManager = service.getTokenManagerAddress(tokenId);
	CustomERC20(tokenAddress).setDistributor(tokenManager);
}

Making existing tokens Interchain

If you already have an ERC-20 token on one or more blockchains, you can turn it into an Interchain Token by deploying Token Managers. Token Managers can be either Lock/Release or Mint/Burn. For Mint/Burn Token Managers, you”ll need to give the Token Manager permissions to mint and burn tokens on your behalf as tokens move between chains.

To clarify this powerful system, we’ll look at two processes for turning existing tokens into Interchain Tokens.

Canonical Tokens (Simple Wrappers)

If you have an ERC-20 token on a single chain, and you’d like a wrapped & bridgeable version to be available on other chains, you can register your ERC-20 as a Canonical Token with the Interchain Token Service. Each token can only be registered a single time as a canonical chain.

Want to try this out? Use Remix to create your own ERC-20 and register your token on the Interchain Token Portal.

You can also do this directly via the Interchain Token Service Smart Contract. Follow these steps to register your token as a canonical token:

First, registerCanonicalToken on the Interchain Token Service. This will deploy a Lock/Release Token Manager on the source chain. Then, deployRemoteCanonical on the Interchain Token Service for each destination chain. This will create an ERC-20 on each destination chain as well as Mint/Burn Token Manager. When tokens are moved from the origin chain to another chain, the token will be locked on the origin chain and minted on the destination chain. If you moved tokens directly from one non-origin chain to another, the token would be burned on the source chain, and minted on the destination chain.

/**
* @notice Used to register canonical tokens. Caller does not matter.
* @param tokenAddress the token to be bridged.
* @return tokenId the tokenId that was used for this canonical token.
*/
function registerCanonicalToken(
	address tokenAddress
) external payable notPaused returns (bytes32 tokenId);
/**
	* @notice Used to deploy remote TokenManagers and standardized tokens for a canonical token. This needs to be
	* called from the chain that registered the canonical token, and anyone can call it.
	* @param tokenId the tokenId of the canonical token.
	* @param destinationChain the name of the chain to deploy the TokenManager and standardized token to.
	* @param gasValue the amount of native tokens to be used to pay for gas for the remote deployment.
	* At least the amount specified needs to be passed to the call
	* @dev `gasValue` exists because this function can be part of a multicall involving multiple functions that could make remote contract calls.
	*/
function deployRemoteCanonicalToken(
	bytes32 tokenId, 
	string calldata destinationChain, 
	uint256 gasValue
) public payable notPaused

Custom Tokens

If you require custom functionality on multiple chains, you must first deploy your custom token on multiple chains, or already have a version of your token on multiple chains.

To turn these deployed tokens into linked Interchain Tokens, register a Token Manager for each one. You can optionally have any of these custom tokens extend IInterchainToken to offer interchainTransfer and interchainTransferFrom methods directly on your token.

You could decide to make all of these Token Managers Mint/Burn, or you could specify at most one (likely your primary/origin chain) to be Lock/Release depending on your needs.

To register a Custom Token via the Interchain Token Service, call the deployCustomTokenManager method.

/**
* @notice Used to deploy custom TokenManagers with the specified salt. Different callers would result in different tokenIds.
* @param salt the salt to be used.
* @param tokenManagerType the type of TokenManager to be deployed.
* @param params the params that will be used to initialize the TokenManager.
*/
function deployCustomTokenManager(
	bytes32 salt,
	TokenManagerType tokenManagerType,
	bytes memory params
) public payable notPaused returns (bytes32 tokenId)

Other Use cases

The Interchain Token Service is a powerful tool for moving tokens between blockchains, and providing you all of the functionality and power you need to make your token interactive wherever it needs to be. Here are some other possibilities for Interchain Tokens.

One of the features of the TokenManager which can be configured is that of the Operator. The Operator is able to manage the flow rates of tokens between chains by calling setFlowLimit on the Interchain Token Service.

Additionally, Interchain Tokens can be made executable. Meaning that they can be sent alongside a standard GMP message. For an example of this, see the example InterchainTokenExecutable.sol

Glossary

To help understand the Interchain Token Service, here are some definitions of terms used in this document.

Smart Contracts

Interchain Token Service

A contract deployed by Axelar that manages the creation and management of Interchain Tokens and Token Managers.

The Interchain Token Service has an address of 0xF786e21509A9D50a9aFD033B5940A2b7D872C208 on all testnet chains, deployed from the v0.3.0 release. Deployed addresses can be found here.

Token Manager

A contract created by the Interchain Token Service that is capable of locking and releasing tokens, or minting and burning them, depending on its type.

Token Managers must be lock/unlock or mint/burn.

Interchain Token

An ERC-20 contract created by the Interchain Token Service or by yourself that is capable of being transferred between block chains. If the contract implements the IInterchainToken interface, it will have knowledge of its own TokenManager and will contain transfer methods directly. If it does not implement this interface, you will need to call functions on the TokenManager to transfer the token.

Properties

TokenID

The ID of the linking between tokens. You can obtain this either

  • Once for each pre-existing ERC20, as a canonical tokenId (getCanonicalTokenId(address))
  • As an address deployer with a bytes32 salt as a custom tokenId (getCustomTokenId(address, bytes32))

Operator

A role for a tokenManager who can set the flowLimit of this manager to limit the influx/outflux of token.

Distributor

A role for tokens that has permission to mint and burn.

Interchain Token Types

Standardized

A minimal ERC-20, that implements the IInterchainToken and IStandardizedToken interfaces and can be deployed by the service.

Custom

A custom ERC-20 that can have any features of functionality you desire, deployed by you. It can optionally implement the IInterchainToken interface to transfer methods directly on your token.

Canonical

A canonical token is an interchain token built from an existing token that is available on multiple chains. The token deployed to other chains will be a Standardized token. There can only be one canonical token for every ERC-20.

Mint/Burn

Incoming token transfers will result in the local minting of new tokens on this blockchain by the Token Manager.

Outgoing token transfers will result in the local burning of received tokens.

Lock/Release

Incoming token transfers will result in the local releasing of locked tokens.

Outgoing token transfers will result in the local locking of tokens on this blockchain by the Token Manager.

Edit this page