logoAcademy

Use any Native as Native Token (DIY)

Learn how to transfer a native token to a new Avalanche L1 and use it as the native token via ICTT.

In this section, you will learn how to transfer a native token from Avalanche’s C-Chain to a new Avalanche L1 using Interchain Token Transfers (ICTT) and set it up to act as the native token on the new L1. This guide will walk you through each step, from creating a L1 to transferring and using the native token.

Create a new blockchain and Deploy on Local Network

Use the avalanche CLI to create a new blockchain where you will deploy the ERC-20 as the native token.

avalanche blockchain create myblockchain  
avalanche blockchain deploy myblockchain

Take note of the important addresses (e.g., Teleporter Registry, Funded Address) from the deployment output as they will be needed in the following steps.

Wrap the Native Token on C-Chain

You'll need to deploy a wrapped token contract for your native token on the C-Chain. The wrapped token will serve as the transferable asset between the chains.

forge create --rpc-url local-c --private-key $PK lib/avalanche-interchain-token-transfer/contracts/src/WrappedNativeToken.sol:WrappedNativeToken

After deployment, save the Deployed to address in an environment variable for future use.

export WRAPPED_NATIVE_C_CHAIN=<address>

Deploy Interchain Token Transfer Contracts

Now, deploy the Interchain Token Transfer contracts on both the C-Chain and the myblockchain to enable cross-chain token transfers.

  • NativeTokenHome Contract on C-Chain
forge create --rpc-url local-c --private-key $PK lib/avalanche-interchain-token-transfer/contracts/src/TokenHome/NativeTokenHome.sol:NativeTokenHome --constructor-args $TELEPORTER_REGISTRY_C_CHAIN $FUNDED_ADDRESS $WRAPPED_NATIVE_C_CHAIN
  • NativeTokenRemote Contract on myblockchain
forge create --rpc-url myblockchain --private-key $PK lib/avalanche-interchain-token-transfer/contracts/src/TokenRemote/NativeTokenRemote.sol:NativeTokenRemote --constructor-args "(${TELEPORTER_REGISTRY_L1}, ${FUNDED_ADDRESS}, ${C_CHAIN_BLOCKCHAIN_ID_HEX}, ${NATIVE_HOME_TRANSFERER_C_CHAIN})" "NATV" 700000000000000000000 0 false 0

Note: Ensure that the initial amount matches the native token amount minted on the C-Chain during the wrapped token deployment.

Export the deployed addresses as environment variables:

export NATIVE_HOME_TRANSFERER_C_CHAIN=<"Deployed to" address>
export NATIVE_TOKEN_REMOTE_L1=<"Deployed to" address>

Grant Native Minting Rights to NativeTokenRemote

To ensure that the NativeTokenRemote contract can mint native tokens on the L1 when ERC-20 tokens are transferred from the C-Chain, the contract must be granted minting rights. This is done by adding the NativeTokenRemote contract address to the Native Minter Precompile.

  1. You will need to interact with the Native Minter Precompile, which resides at a fixed address on all Avalanche L1s:
    Native Minter Precompile Address: 0x0200000000000000000000000000000000000001

  2. Use the following command to grant the NativeTokenRemote contract minting rights by setting it as an enabled address on the Native Minter Precompile:

cast send --rpc-url myblockchain --private-key $PK 0x0200000000000000000000000000000000000001 "setEnabled(address)" $NATIVE_TOKEN_REMOTE_L1
  • $NATIVE_TOKEN_REMOTE_L1: The deployed address of the NativeTokenRemote contract on your L1.

Once this step is completed, the NativeTokenRemote contract will have the necessary permissions to mint native tokens when ERC-20 tokens are transferred from the C-Chain.

Register Remote Token with Home Transferer

Register the remote token on the home chain so that it recognizes the transferer contracts.

cast send --rpc-url myblockchain --private-key $PK $NATIVE_TOKEN_REMOTE_L1 "registerWithHome((address, uint256))" "(0x0000000000000000000000000000000000000000, 0)"

Collateralize and Transfer Tokens

Collateralize the home contract by locking native tokens. The amount of collateral should match the initial token reserve set on the myblockchain.

  • Approve Tokens for Transfer
    Approve a certain number of tokens to be used by the Home Transferer.
cast send --rpc-url local-c --private-key $PK $ERC20_HOME_C_CHAIN "approve(address, uint256)" $ERC20_HOME_TRANSFERER_C_CHAIN 2000000000000000000000
  • Add Collateral and Send Tokens
    Add collateral to the transferer contract.
cast send --rpc-url local-c --private-key $PK $ERC20_HOME_TRANSFERER_C_CHAIN "addCollateral(bytes32, address, uint256)" $L1_BLOCKCHAIN_ID_HEX $NATIVE_TOKEN_REMOTE_L1 100000000000000000000

Send tokens to the L1.

cast send --rpc-url local-c --private-key $PK $ERC20_HOME_TRANSFERER_C_CHAIN "send((bytes32, address, address, address, uint256, uint256, uint256, address), uint256)" "(${L1_BLOCKCHAIN_ID_HEX}, ${NATIVE_TOKEN_REMOTE_L1}, ${FUNDED_ADDRESS}, ${ERC20_HOME_C_CHAIN}, 0, 0, 250000, 0x0000000000000000000000000000000000000000)" 1000000000000000000000

Check Balances

Finally, check the balance on the L1 to confirm that the tokens were successfully transferred and minted.

cast balance --rpc-url myblockchain $FUNDED_ADDRESS

You can also verify that the token is collateralized:

cast call --rpc-url myblockchain $NATIVE_TOKEN_REMOTE_L1 "isCollateralized()(bool)"

Conclusion

By following these steps, you’ll successfully transfer a native token from the C-Chain to a L1 and use it as the native token via Avalanche’s Interchain Token Transfer system.

For more detailed information, refer to the refer to the official Avalanche ICTT documentation.

On this page