Interchain Transfer

Tokens connected to the Interchain Token Service (ITS) can be transferred between chains by using the interchainTransfer() function. The interchainTransfer() function is defined on the ITS edge contract. In addition to existing on the ITS contract itself, tokens inheriting from the Interchain Token Standard will also have access to the interchainTransfer() function, so you can send an interchain transfer directly from the token contract itself.

The interchainTransfer() function takes the following parameters

  1. tokenId: The interchainTokenId of the token being sent.
  2. destinationChain: The name of the chain the token is being sent to.
  3. destinationAddress: The receiving address of the cross-chain transfer.
  4. amount: The amount of tokens being sent.

It is defined as follows:

function interchainTransfer(
bytes32 tokenId,
string calldata destinationChain,
bytes calldata destinationAddress,
uint256 amount
) external payable{}

When triggered, ITS via the Token Handler Pulls the tokens from msg.sender using takeToken() function. For mint/burn managers, this will involve burning the token on the source whereas for lock/unlock managers, this will involve escrows/locks on the source via the safeTransferFrom() function. The takeToken() function will also decrement the flow limit for the token being moved out of that blockchain.

With the token now either burnt or held by the Token Manager ITS will then send a cross-chain GMP message with a payload containing the following:

bytes memory payload = abi.encode(
MESSAGE_TYPE_INTERCHAIN_TRANSFER, //message type identifier
tokenId,
sourceAddress.toBytes(),
destinationAddress,
amount,
data
);

Once the GMP message arrives to the destination chain, ITS will then call the giveToken() function to either mint or unlock tokens to for the end receiver (depending on which Token Manager Type is used). The giveToken() function will also increment the flow limit for the token being moved into that blockchain.

You can see a live example of an interchain transfer being called here on the Axelarscan Explorer.

Refer to the diagram below to see how the interchainTransfer() function works.

Your browser does not support SVG

Common errors and their meanings:

ErrorDescriptionResolution
NotTokenCaller is not the expected tokenOnly the token contract can call certain functions
ZeroAmountTransfer amount is 0Provide a non-zero amount
EmptyDestinationAddressNo destination address providedInclude valid destination address
FlowLimitExceededTransfer exceeds flow limitWait for next epoch or reduce amount
UntrustedChainDestination chain not trustedContact operators to add chain
PausedService is pausedWait for service to be unpaused
TakeTokenFailedFailed to take tokens from senderEnsure sufficient balance and approval
GiveTokenFailedFailed to give tokens to recipientCheck token manager configuration
  1. Always verify destination chain names - Use exact chain names as registered in ITS
  2. Encode addresses correctly - Follow chain-specific encoding requirements
  3. Provide sufficient gas - Calculate gas needs based on destination chain costs
  4. Monitor flow limits - Check current flow before large transfers
  5. Handle failures gracefully - Implement retry logic for failed transfers
  6. Test on testnet first - Verify complete flow before mainnet deployment
  7. Use event monitoring - Track InterchainTransfer events for confirmation
  8. Implement receive handlers - For contract calls, ensure proper token handling

Edit on GitHub