Enable your tokens in CCIP (Burn & Mint): Register from an EOA using Hardhat

Guide Versions

This guide is available in multiple versions. Choose the one that matches your needs.

This tutorial will guide you through the process of enabling your own tokens in CCIP using Hardhat. You will learn how to deploy tokens and set up Burn & Mint token pools. After that, you will register them in CCIP and configure them without needing manual intervention. Finally, you will test the Burn & Mint token handling mechanism, where tokens are burned on the source blockchain and an equivalent amount is minted on the destination blockchain.

We will cover the following key steps:

  1. Deploying Tokens: You will deploy your BurnMintERC20 tokens on the Avalanche Fuji and Arbitrum Sepolia testnets.

  2. Deploying Token Pools: Once your tokens are deployed, you will deploy BurnMintTokenPool token pools on Avalanche Fuji and Arbitrum Sepolia. These pools are essential for minting and burning tokens during cross-chain transfers. Each token will be linked to a pool, which will manage token transfers and ensure proper handling of assets across chains.

  3. Claiming Mint and Burn Roles: You will claim the mint and burn roles for the token pools, allowing your token pools to control how tokens are minted and burned during cross-chain transfers.

  4. Claiming and Accepting the Admin Role: This is a two-step process:

    1. You will call the RegistryModuleOwnerCustom contract's registerAdminViaOwner function to register your EOA as the token admin. This role is required to enable your token in CCIP.

    2. Once claimed, you will call the TokenAdminRegistry contract's acceptAdminRole function to complete the registration process.

  5. Linking Tokens to Pools: You will call the TokenAdminRegistry contract's setPool function to associate each token with its respective token pool.

  6. Configuring Token Pools: You will call the applyChainUpdates function on your token pools to configure each pool by setting cross-chain transfer parameters, such as token pool rate limits and enabled destination chains.

  7. Minting Tokens: You will call the mint function to mint tokens on Avalanche Fuji for your EOA. These tokens will later be used to test cross-chain transfers to Arbitrum Sepolia.

  8. Transferring Tokens: Finally, you will transfer tokens from Avalanche Fuji to Arbitrum Sepolia using CCIP. You will have the option to pay CCIP fees in either LINK tokens or native gas tokens.

By the end of this tutorial, you will have successfully deployed, registered, configured, and enabled your tokens and token pools for use in CCIP.

Before You Begin

  1. Make sure you have Node.js v22.10.0 or above installed. If not, install Node.js v22.10.0:

    Download Node.js v22.10.0 if you don't have it installed. Optionally, you can use the nvm package to switch between Node.js versions:

    nvm use 22
    

    Verify that the correct version of Node.js is installed:

    node -v
    

    Example output:

    $ node -v
    v22.15.0
    
  2. Clone the repository and navigate to the project directory:

    git clone https://github.com/smartcontractkit/smart-contract-examples.git
    cd smart-contract-examples/ccip/cct/hardhat
    
  3. Install dependencies for the project:

    npm install
    
  4. Compile the project:

    npm run compile
    
  5. Encrypt your environment variables for higher security:
    The project uses @chainlink/env-enc to encrypt your environment variables at rest. Follow the steps below to configure your environment securely:

    1. Set an encryption password for your environment variables:

      npx env-enc set-pw
      
    2. Set up a .env.enc file with the necessary variables for Avalanche Fuji and Ethereum Sepolia. Use the following command to add the variables:

      npx env-enc set
      

      Variables to configure:

      • AVALANCHE_FUJI_RPC_URL: A URL for the Avalanche Fuji testnet. You can get a personal endpoint from services like Alchemy or Infura.
      • ETHEREUM_SEPOLIA_RPC_URL: A URL for the Ethereum Sepolia testnet. You can sign up for a personal endpoint from Alchemy or Infura.
      • PRIVATE_KEY: The private key for your testnet wallet. If you use MetaMask, you can follow this guide to export your private key. Note: This key is required for signing transactions like token transfers.
      • ETHERSCAN_API_KEY: An API key from Etherscan to verify your contracts. You can obtain one from Etherscan.
  6. Fund your EOA with LINK and native gas tokens:
    Make sure your EOA has enough LINK and native gas tokens on Avalanche Fuji and Ethereum Sepolia to cover transaction fees. You can use the Chainlink faucets to get testnet tokens.

Tutorial

Deploy Tokens

In this step, you will use the deployToken task to deploy tokens on two testnets, Avalanche Fuji and Ethereum Sepolia. Below is an explanation of the parameters used during deployment:

ParameterDescriptionDefaultRequired
nameThe name of the token. This is the full name by which the token will be identified.N/AYes
symbolThe symbol of the token. This is the shorthand (usually 3-5 letters) representing the token.N/AYes
decimalsThe number of decimals the token will use. For instance, 18 decimals means 1 token is represented as 1e18 smallest units.18No
maxsupplyThe maximum supply of tokens. Use 0 for unlimited supply.0No
premintThe amount of tokens to be minted to the owner at the time of deployment. If set to 0, no tokens will be minted to the owner during deployment.0No
verifycontractFlag to verify the contract on Etherscan or a similar blockchain explorer. Pass this flag to enable verification, omit to skip.falseNo
networkThe blockchain on which the token will be deployed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Deploy tokens, use the following commands, substituting the token name and symbol as needed:

  1. Deploy the token on Avalanche Fuji:

    npx hardhat deployToken --name "BnM sak" --symbol BnMsak --decimals 18 --maxsupply 0 --premint 100000000000000000000 --verifycontract --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T15:48:05.691Z info: 🚀 Deploying BurnMintERC20 to avalancheFuji...
    2025-10-21T15:48:05.692Z info:    name: BnM sak, symbol: BnMsak
    2025-10-21T15:48:43.684Z info: ⏳ Deployment tx: 0x36109e1ff82c5063e231e036ea9d4d0d66421ff5edd61a0d5767e95793f54eb5
    2025-10-21T15:48:43.684Z info:    Waiting for 2 confirmation(s)...
    2025-10-21T15:49:07.361Z info: ✅ Token deployed at: 0xb613B55897F07eAF430bF9a509498e55487305Ea
    2025-10-21T15:49:09.119Z info: Granting mint and burn roles to 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA...
    2025-10-21T15:49:10.392Z info:    Waiting for 2 confirmation(s)...
    2025-10-21T15:50:20.800Z info: ✅ Mint/Burn roles granted.
    2025-10-21T15:50:20.801Z info: Verifying contract...
    
    📤 Submitted source code for verification on SnowTrace:
    
       @chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol:BurnMintERC20
       Address: 0xb613B55897F07eAF430bF9a509498e55487305Ea
    
    ⏳ Waiting for verification result...
    
    
    ✅ Contract verified successfully on SnowTrace!
    
       @chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol:BurnMintERC20
       Explorer: https://testnet.snowtrace.io/address/0xb613B55897F07eAF430bF9a509498e55487305Ea#code
    2025-10-21T15:50:30.197Z info: ✅ Token contract verified successfully
    
  2. Deploy the token on Ethereum Sepolia:

    npx hardhat deployToken --name "BnM sak" --symbol BnMsak --decimals 18 --maxsupply 0 --premint 100000000000000000000 --verifycontract --network ethereumSepolia
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T15:57:35.979Z info: 🚀 Deploying BurnMintERC20 to ethereumSepolia...
    2025-10-21T15:57:35.980Z info:    name: BnM sak, symbol: BnMsak
    2025-10-21T15:57:47.934Z info: ⏳ Deployment tx: 0xa1559da1474d9a062a63b57f86e4c6047c8918778b4abe5c7f911a85b502094b
    2025-10-21T15:57:47.934Z info:    Waiting for 3 confirmation(s)...
    2025-10-21T15:58:54.199Z info: ✅ Token deployed at: 0x6803e72f0af827577a49FC82d7Ed9291028d687c
    2025-10-21T15:58:55.814Z info: Granting mint and burn roles to 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA...
    2025-10-21T15:59:00.841Z info:    Waiting for 3 confirmation(s)...
    2025-10-21T15:59:37.640Z info: ✅ Mint/Burn roles granted.
    2025-10-21T15:59:37.640Z info: Verifying contract...
    
    📤 Submitted source code for verification on Etherscan:
    
       @chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol:BurnMintERC20
       Address: 0x6803e72f0af827577a49FC82d7Ed9291028d687c
    
    ⏳ Waiting for verification result...
    
    
    ✅ Contract verified successfully on Etherscan!
    
       @chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol:BurnMintERC20
       Explorer: https://sepolia.etherscan.io/address/0x6803e72f0af827577a49FC82d7Ed9291028d687c#code
    2025-10-21T16:00:05.431Z info: ✅ Token contract verified successfully
    

Deploy Token Pools

In this step, you will use the deployTokenPool task to deploy token pools for the tokens on both testnets, Avalanche Fuji and Ethereum Sepolia. Below is an explanation of the parameters used during deployment:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token for which the pool is being created.N/AYes
pooltypeThe type of pool to deploy. For this tutorial, we use "burnMint" for a pool that supports burning and minting of tokens."burnMint"No
localtokendecimalsThe number of decimals for the token on this chain.18No
verifycontractFlag to verify the contract on Etherscan or a similar blockchain explorer. Pass this flag to enable verification, omit to skip.falseNo
networkThe blockchain on which the token pool will be deployed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Deploy token pools using the following commands, replacing the token address with the one you deployed in the previous step:

  1. Deploy the burn and mint token pool on Avalanche Fuji:

    npx hardhat deployTokenPool \
      --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea \
      --pooltype burnMint \
      --localtokendecimals 18 \
      --verifycontract \
      --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:03:29.749Z info: 🚀 Deploying burnMint pool on avalancheFuji
    2025-10-21T16:03:29.750Z info:    Token: 0xb613B55897F07eAF430bF9a509498e55487305Ea
    2025-10-21T16:03:29.750Z info:    Decimals: 18
    2025-10-21T16:03:29.750Z info:    Allowlist: None
    2025-10-21T16:04:31.691Z info: ⏳ Deployment tx: 0xc91a7fb0f1e77531bc49e9ce3c4de5f0bf8797e9e031e23c707b22b50fbb1547
    2025-10-21T16:04:31.692Z info:    Waiting for 2 confirmation(s)...
    2025-10-21T16:04:32.196Z info: ✅ Token pool deployed at: 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A
    2025-10-21T16:04:32.196Z info: Granting mint and burn roles to 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A on token 0xb613B55897F07eAF430bF9a509498e55487305Ea
    2025-10-21T16:04:33.856Z info:    Waiting for 2 confirmation(s)...
    2025-10-21T16:05:45.050Z info: ✅ Mint/Burn roles granted
    2025-10-21T16:05:45.051Z info: Verifying contract...
    
    📤 Submitted source code for verification on SnowTrace:
    
       @chainlink/contracts-ccip/contracts/pools/BurnMintTokenPool.sol:BurnMintTokenPool
       Address: 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A
    
    ⏳ Waiting for verification result...
    
    
    ✅ Contract verified successfully on SnowTrace!
    
       @chainlink/contracts-ccip/contracts/pools/BurnMintTokenPool.sol:BurnMintTokenPool
       Explorer: https://testnet.snowtrace.io/address/0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A#code
    2025-10-21T16:05:59.699Z info: ✅ Token pool contract verified successfully
    
  2. Deploy the burn and mint token pool on Ethereum Sepolia:

    npx hardhat deployTokenPool \
      --tokenaddress 0x6803e72f0af827577a49FC82d7Ed9291028d687c \
      --pooltype burnMint \
      --localtokendecimals 18 \
      --verifycontract \
      --network ethereumSepolia
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:08:04.592Z info: 🚀 Deploying burnMint pool on ethereumSepolia
    2025-10-21T16:08:04.593Z info:    Token: 0x6803e72f0af827577a49FC82d7Ed9291028d687c
    2025-10-21T16:08:04.593Z info:    Decimals: 18
    2025-10-21T16:08:04.593Z info:    Allowlist: None
    2025-10-21T16:08:31.645Z info: ⏳ Deployment tx: 0x10e0b153a0a3e3fe3eccd512403fa01aa8c4a9c017e2f15293da85bf3d0fbc55
    2025-10-21T16:08:31.645Z info:    Waiting for 3 confirmation(s)...
    2025-10-21T16:08:51.518Z info: ✅ Token pool deployed at: 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D
    2025-10-21T16:08:51.518Z info: Granting mint and burn roles to 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D on token 0x6803e72f0af827577a49FC82d7Ed9291028d687c
    2025-10-21T16:08:57.229Z info:    Waiting for 3 confirmation(s)...
    2025-10-21T16:09:27.333Z info: ✅ Mint/Burn roles granted
    2025-10-21T16:09:27.333Z info: Verifying contract...
    
    📤 Submitted source code for verification on Etherscan:
    
       @chainlink/contracts-ccip/contracts/pools/BurnMintTokenPool.sol:BurnMintTokenPool
       Address: 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D
    
    ⏳ Waiting for verification result...
    
    
    ✅ Contract verified successfully on Etherscan!
    
       @chainlink/contracts-ccip/contracts/pools/BurnMintTokenPool.sol:BurnMintTokenPool
       Explorer: https://sepolia.etherscan.io/address/0xA29878301cA30a4639C33cD7EC8061E4265E1a5D#code
    2025-10-21T16:09:53.510Z info: ✅ Token pool contract verified successfully
    

Claim Admin

In this step, you will use the claimAdmin task to register your EOA as the administrator for the deployed tokens on both testnets, Avalanche Fuji and Ethereum Sepolia. This process involves calling the RegistryModuleOwnerCustom contract, which will fetch the CCIP admin of the token and set it up as the admin in the registry.

Below is an explanation of the parameters used during the admin claim process:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token for which the admin role is being claimed.N/AYes
networkThe blockchain on which the claim admin process will be executed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Claim the admin role by using the following commands, replacing the token address with the one you deployed in the previous steps:

  1. Claim the admin role on Avalanche Fuji:

    npx hardhat claimAdmin --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:28:08.196Z info: 🎯 Claiming admin for 0xb613B55897F07eAF430bF9a509498e55487305Ea using getCCIPAdmin mode
    2025-10-21T16:28:11.832Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is CCIP admin
    2025-10-21T16:29:04.511Z info: 📤 TX sent: 0xa15fcb890ac37b81d3ecec9560624e38b7d127177c01af7d9359ab5f6b6ca97c. Waiting for 2 confirmations...
    2025-10-21T16:29:13.730Z info: ✅ Admin claimed for 0xb613B55897F07eAF430bF9a509498e55487305Ea on avalancheFuji (2 confirmations)
    
  2. Claim the admin role on Ethereum Sepolia:

    npx hardhat claimAdmin --tokenaddress 0x6803e72f0af827577a49FC82d7Ed9291028d687c --network ethereumSepolia
    

    Example output:

    2025-10-21T16:30:14.261Z info: 🎯 Claiming admin for 0x6803e72f0af827577a49FC82d7Ed9291028d687c using getCCIPAdmin mode
    2025-10-21T16:30:23.319Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is CCIP admin
    2025-10-21T16:30:30.196Z info: 📤 TX sent: 0x5c7e4644fc88d8df99ce8557665a78037951c748c927b012bb4565285241ae3a. Waiting for 3 confirmations...
    2025-10-21T16:31:02.943Z info: ✅ Admin claimed for 0x6803e72f0af827577a49FC82d7Ed9291028d687c on ethereumSepolia (3 confirmations)
    

Accept Admin Role

In this step, you will use the acceptAdminRole task to accept the admin role for the deployed tokens on both testnets, Avalanche Fuji and Ethereum Sepolia. Once you have claimed the role, accepting the role finalizes your control over the token administration.

Below is an explanation of the parameters used during the admin role acceptance process:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token for which the admin role is being accepted.N/AYes
networkThe blockchain on which the accept admin process will be executed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Accept the admin role by using the following commands, replacing the token address with the one deployed in the previous steps:

  1. Accept the admin role on Avalanche Fuji:

    npx hardhat acceptAdminRole --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:32:22.560Z info: 🔄 Accepting admin role for 0xb613B55897F07eAF430bF9a509498e55487305Ea on avalancheFuji...
    2025-10-21T16:32:25.385Z info: Checking pending admin for 0xb613B55897F07eAF430bF9a509498e55487305Ea...
    2025-10-21T16:32:25.641Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is the pending admin
    2025-10-21T16:32:25.641Z info: Accepting admin role...
    2025-10-21T16:33:07.931Z info: 📤 TX sent: 0xa7b57a5d7c29828ddf4941c48877c02d36cbc5ec9a4ba401548fef9163256abb. Waiting for 2 confirmations...
    2025-10-21T16:33:24.516Z info: ✅ Admin role accepted for 0xb613B55897F07eAF430bF9a509498e55487305Ea on avalancheFuji (2 confirmations)
    
  2. Accept the admin role on Ethereum Sepolia:

    npx hardhat acceptAdminRole --tokenaddress 0x6803e72f0af827577a49FC82d7Ed9291028d687c --network ethereumSepolia
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:35:18.634Z info: 🔄 Accepting admin role for 0x6803e72f0af827577a49FC82d7Ed9291028d687c on ethereumSepolia...
    2025-10-21T16:35:26.364Z info: Checking pending admin for 0x6803e72f0af827577a49FC82d7Ed9291028d687c...
    2025-10-21T16:35:26.688Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is the pending admin
    2025-10-21T16:35:26.688Z info: Accepting admin role...
    2025-10-21T16:35:29.020Z info: 📤 TX sent: 0x5ede40fac823712bfa465f30258dcb5c90a3863f10db4e92d83d5165965221cd. Waiting for 3 confirmations...
    2025-10-21T16:36:02.952Z info: ✅ Admin role accepted for 0x6803e72f0af827577a49FC82d7Ed9291028d687c on ethereumSepolia (3 confirmations)
    

Set Pool

In this step, you will use the setPool task to link each token with its respective token pool on both testnets.

Below is an explanation of the parameters used during the pool setting process:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token to be linked to a pool.N/AYes
pooladdressThe address of the pool associated with the token.N/AYes
networkThe blockchain on which the pool setting will be executed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Link each token with its respective token pool by using the following commands, replacing the token and pool addresses with the ones you deployed in the previous steps:

  1. Set the pool for Avalanche Fuji:

    npx hardhat setPool --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --pooladdress 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:37:52.758Z info: 🔗 Setting pool for token 0xb613B55897F07eAF430bF9a509498e55487305Ea on avalancheFuji...
    2025-10-21T16:37:55.823Z info: 🔹 Using signer: 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca
    2025-10-21T16:37:55.823Z info: Using TokenAdminRegistry: 0xA92053a4a3922084d992fD2835bdBa4caC6877e6
    2025-10-21T16:37:56.225Z info: Checking token configuration for 0xb613B55897F07eAF430bF9a509498e55487305Ea...
    2025-10-21T16:37:56.471Z info: Token 0xb613B55897F07eAF430bF9a509498e55487305Ea current admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
    2025-10-21T16:37:56.471Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is the token administrator
    2025-10-21T16:37:56.471Z info: Setting pool 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A for token 0xb613B55897F07eAF430bF9a509498e55487305Ea...
    2025-10-21T16:38:05.847Z info: 📤 TX sent: 0xc06c155a0a581a83cadec3e6c2d41f1291c255f27fd9a2bfccaa349e8d22527f. Waiting for 2 confirmations...
    2025-10-21T16:39:22.658Z info: ✅ Pool successfully set for token 0xb613B55897F07eAF430bF9a509498e55487305Ea → 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A on avalancheFuji (2 confirmations)
    
  2. Set the pool for Ethereum Sepolia:

    npx hardhat setPool --tokenaddress 0x6803e72f0af827577a49FC82d7Ed9291028d687c --pooladdress 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D --network ethereumSepolia
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:42:30.911Z info: 🔗 Setting pool for token 0x6803e72f0af827577a49FC82d7Ed9291028d687c on ethereumSepolia...
    2025-10-21T16:42:39.838Z info: 🔹 Using signer: 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca
    2025-10-21T16:42:39.838Z info: Using TokenAdminRegistry: 0x95F29FEE11c5C55d26cCcf1DB6772DE953B37B82
    2025-10-21T16:42:40.266Z info: Checking token configuration for 0x6803e72f0af827577a49FC82d7Ed9291028d687c...
    2025-10-21T16:42:40.702Z info: Token 0x6803e72f0af827577a49FC82d7Ed9291028d687c current admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
    2025-10-21T16:42:40.702Z info: ✅ Current wallet 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca is the token administrator
    2025-10-21T16:42:40.702Z info: Setting pool 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D for token 0x6803e72f0af827577a49FC82d7Ed9291028d687c...
    2025-10-21T16:42:45.309Z info: 📤 TX sent: 0x994e1e97275ee1ed7b0135afdf8b85071899036bde490602590cda05ab7e5dda. Waiting for 3 confirmations...
    2025-10-21T16:43:16.490Z info: ✅ Pool successfully set for token 0x6803e72f0af827577a49FC82d7Ed9291028d687c → 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D on ethereumSepolia (3 confirmations)
    

Configure Token Pools

In this step, you will use the applyChainUpdates task to initialize the token pool configuration on each blockchain to enable cross-chain transfers between Avalanche Fuji and Ethereum Sepolia. Below is an explanation of the parameters used:

ParameterDescriptionDefaultRequired
pooladdressThe address of the pool to be configured.N/AYes
remotechainThe remote blockchain network (e.g., ethereumSepolia for Fuji pool, avalancheFuji for Sepolia pool).N/AYes
remotepooladdressesComma-separated list of remote pool addresses.N/AYes
remotetokenaddressThe address of the token on the remote chain.N/AYes
outboundratelimitenabledFlag to enable outbound rate limits for cross-chain transfers. Pass this flag to enable, omit to disable.falseNo
outboundratelimitcapacityMaximum capacity for the outbound rate limiter (in wei).0No
outboundratelimitrateRefill rate for the outbound rate limiter bucket (tokens per second, in wei).0No
inboundratelimitenabledFlag to enable inbound rate limits for cross-chain transfers. Pass this flag to enable, omit to disable.falseNo
inboundratelimitcapacityMaximum capacity for the inbound rate limiter (in wei).0No
inboundratelimitrateRefill rate for the inbound rate limiter bucket (tokens per second, in wei).0No

Configure the pools using the following commands, replacing the pool, token, and remote pool addresses with those you deployed in the previous steps:

  1. Configure the pool on Avalanche Fuji:

    npx hardhat applyChainUpdates \
      --pooladdress 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A \
      --remotechain ethereumSepolia \
      --remotepooladdresses 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D \
      --remotetokenaddress 0x6803e72f0af827577a49FC82d7Ed9291028d687c \
      --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:51:34.417Z info: === Starting Chain Update Configuration ===
    2025-10-21T16:51:34.418Z info: 🔹 Local network: avalancheFuji
    2025-10-21T16:51:34.418Z info: 🔹 Pool address: 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A
    2025-10-21T16:51:34.418Z info: 🔹 Remote chain: ethereumSepolia
    2025-10-21T16:51:34.418Z info: 🔹 Remote chain family: evm
    2025-10-21T16:51:34.418Z info: 🔹 Remote chain selector: 16015286601757825753
    2025-10-21T16:51:36.581Z info: ✅ All addresses validated successfully
    2025-10-21T16:51:37.100Z info: ✅ Using signer: 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca
    2025-10-21T16:51:37.504Z info: ✅ Connected to TokenPool contract
    2025-10-21T16:51:37.505Z info:   Remote pool 1: 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D → 0x000000000000000000000000a29878301ca30a4639c33cd7ec8061e4265e1a5d
    2025-10-21T16:51:37.506Z info: === Rate Limiter Configuration ===
    2025-10-21T16:51:37.506Z info: Outbound enabled: false
    2025-10-21T16:51:37.506Z info: Inbound enabled: false
    2025-10-21T16:51:37.506Z info: === Executing applyChainUpdates() ===
    2025-10-21T16:52:05.003Z info: 📤 TX sent: 0xde6b43d51e34668267eccdb188402b12c3e7497a918f17dd93521c504efc22db
    2025-10-21T16:52:05.003Z info: Waiting for 2 confirmations...
    2025-10-21T16:52:21.542Z info: ✅ Chain update applied successfully on avalancheFuji (2 confirmations)!
    
  2. Configure the pool on Ethereum Sepolia:

    npx hardhat applyChainUpdates \
      --pooladdress 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D \
      --remotechain avalancheFuji \
      --remotetokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea \
      --remotepooladdresses 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A \
      --network ethereumSepolia
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T16:59:10.675Z info: === Starting Chain Update Configuration ===
    2025-10-21T16:59:10.676Z info: 🔹 Local network: ethereumSepolia
    2025-10-21T16:59:10.676Z info: 🔹 Pool address: 0xA29878301cA30a4639C33cD7EC8061E4265E1a5D
    2025-10-21T16:59:10.676Z info: 🔹 Remote chain: avalancheFuji
    2025-10-21T16:59:10.676Z info: 🔹 Remote chain family: evm
    2025-10-21T16:59:10.676Z info: 🔹 Remote chain selector: 14767482510784806043
    2025-10-21T16:59:12.799Z info: ✅ All addresses validated successfully
    2025-10-21T16:59:13.366Z info: ✅ Using signer: 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca
    2025-10-21T16:59:13.699Z info: ✅ Connected to TokenPool contract
    2025-10-21T16:59:13.700Z info:   Remote pool 1: 0x5e8b0e5EAC57d73E7b93d85b8eA3fcaDa282868A → 0x0000000000000000000000005e8b0e5eac57d73e7b93d85b8ea3fcada282868a
    2025-10-21T16:59:13.701Z info: === Rate Limiter Configuration ===
    2025-10-21T16:59:13.701Z info: Outbound enabled: false
    2025-10-21T16:59:13.701Z info: Inbound enabled: false
    2025-10-21T16:59:13.701Z info: === Executing applyChainUpdates() ===
    2025-10-21T16:59:15.699Z info: 📤 TX sent: 0xddcb3cae44fe84d05b47e1c5ee96e8290104005f4c01501416410c767542aa55
    2025-10-21T16:59:15.699Z info: Waiting for 3 confirmations...
    2025-10-21T16:59:51.435Z info: ✅ Chain update applied successfully on ethereumSepolia (3 confirmations)!
    

Mint Tokens

In this step, you will use the mintTokens task to mint tokens on Avalanche Fuji for your Externally Owned Account (EOA). Since you assigned mint and burn privileges to your EOA when deploying the tokens in the first step, you can now mint tokens for testing purposes. This is to ensure that you have enough tokens in your EOA to perform cross-chain transfers in the next step.

You will interact with the BurnMintERC20 token contract, specifically calling the mint() function to mint tokens to your EOA.

Below is an explanation of the parameters used during the minting process:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token for which tokens are being minted.N/AYes
amountThe amount of tokens to mint (in wei).N/AYes
receiveraddressThe address of the receiver of the minted tokens. If not provided, defaults to your EOA.N/ANo
networkThe blockchain on which the minting process will be executed. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Mint tokens to your EOA using the following command, replacing the token address with the one you deployed in the previous steps:

  1. Mint tokens on Avalanche Fuji:

    npx hardhat mintTokens --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --amount 1000000000000000000000 --network avalancheFuji
    

    Example output:

    ✅ Tasks loaded from /tasks/index.ts
    2025-10-21T17:00:46.902Z info: 🪙 Minting 1000000000000000000000 BnMsak to 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca...
    2025-10-21T17:00:48.879Z info: ⏳ Mint tx: 0xe2759da0ba03aa64bb488acd6518ebd5a927dd99e5df2116c9b6b324506a8a2a
    2025-10-21T17:00:48.879Z info:    Waiting for 2 confirmation(s)...
    2025-10-21T17:00:58.287Z info: ✅ Minted 1000000000000000000000 BnMsak to 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca
    2025-10-21T17:00:58.287Z info:    Current balance of 0x8c244f0b2164e6a3bed74ab429b0ebd661bb14ca: 1100000000000000000000 BnMsak
    

Transfer Tokens

In this step, you will use the transferTokens task to transfer tokens from Avalanche Fuji to Ethereum Sepolia using CCIP. You have two options for paying CCIP fees: using LINK tokens or native gas tokens.

You will interact with the IRouterClient contract, specifically calling the ccipSend() function to initiate the token transfer.

Below is an explanation of the parameters used during the token transfer process:

ParameterDescriptionDefaultRequired
tokenaddressThe address of the token being transferred.N/AYes
amountThe amount of tokens to transfer.N/AYes
destinationchainThe blockchain to which the tokens will be transferred. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes
receiveraddressThe address of the receiver on the destination blockchain.N/AYes
feeThe type of fee used for the transfer, either LINK or native.LINKNo
networkThe blockchain on which the token transfer will be initiated. Examples include avalancheFuji, ethereumSepolia, baseSepolia, and arbitrumSepolia.N/AYes

Call the CCIP Router to transfer tokens from Avalanche Fuji to Ethereum Sepolia, paying the CCIP fees in LINK tokens. Replace the token address, amount, receiver address, and blockchain with the appropriate values:

npx hardhat transferTokens --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --amount 100000000000000000000 --destinationchain ethereumSepolia --receiveraddress 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf --network avalancheFuji

Example output:

✅ Tasks loaded from /tasks/index.ts
2025-10-21T17:02:33.667Z info: 🚀 Transferring 100000000000000000000 tokens via CCIP from avalancheFuji to ethereumSepolia...
2025-10-21T17:02:33.669Z info:    Token: 0xb613B55897F07eAF430bF9a509498e55487305Ea
2025-10-21T17:02:33.669Z info:    Receiver: 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf
2025-10-21T17:02:33.669Z info:    Fee token: LINK
2025-10-21T17:02:34.619Z info: 💰 Estimated fees: 12147121320763453
2025-10-21T17:02:34.877Z info: Approving 100000000000000000000 tokens for router 0xF694E193200268f9a4868e4Aa017A0118C9a8177
2025-10-21T17:02:36.962Z info:    Waiting for 2 confirmation(s)...
2025-10-21T17:02:42.129Z info: Approving 12147121320763453 LINK to router
2025-10-21T17:02:43.439Z info:    Waiting for 2 confirmation(s)...
2025-10-21T17:02:52.641Z info: 💰 Estimated CCIP fees: 12147121320763453
2025-10-21T17:02:52.642Z info: Sending CCIP message...
2025-10-21T17:02:53.934Z info: ⏳ CCIP message tx: 0x7b7bccaf0e29b3378a97ca0eb5c812b1fd54e97ab2c7072986abfbaf4844040a
2025-10-21T17:02:53.934Z info:    Waiting for 2 confirmation(s)...
2025-10-21T17:03:07.544Z info: ✅ CCIP message sent successfully
2025-10-21T17:03:07.544Z info:    Transaction: 0x7b7bccaf0e29b3378a97ca0eb5c812b1fd54e97ab2c7072986abfbaf4844040a
2025-10-21T17:03:07.545Z info:    Check status: https://ccip.chain.link/tx/0x7b7bccaf0e29b3378a97ca0eb5c812b1fd54e97ab2c7072986abfbaf4844040a
2025-10-21T17:03:07.545Z info: 📋 Transfer Summary:
2025-10-21T17:03:07.545Z info:    Token: 0xb613B55897F07eAF430bF9a509498e55487305Ea
2025-10-21T17:03:07.545Z info:    Amount: 100000000000000000000
2025-10-21T17:03:07.545Z info:    From: avalancheFuji
2025-10-21T17:03:07.545Z info:    To: ethereumSepolia
2025-10-21T17:03:07.545Z info:    Receiver: 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf
2025-10-21T17:03:07.545Z info:    Fee paid in: LINK

Pay fees in native gas tokens

Call the CCIP Router to transfer tokens from Avalanche Fuji to Ethereum Sepolia, paying the CCIP fees in native gas tokens. Replace the token address, amount, receiver address, and blockchain with the appropriate values:

npx hardhat transferTokens --tokenaddress 0xb613B55897F07eAF430bF9a509498e55487305Ea --amount 100000000000000000000 --destinationchain ethereumSepolia --receiveraddress 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf --fee native --network avalancheFuji

Example output:

✅ Tasks loaded from /tasks/index.ts
2025-10-21T17:04:37.591Z info: 🚀 Transferring 100000000000000000000 tokens via CCIP from avalancheFuji to ethereumSepolia...
2025-10-21T17:04:37.592Z info:    Token: 0xb613B55897F07eAF430bF9a509498e55487305Ea
2025-10-21T17:04:37.592Z info:    Receiver: 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf
2025-10-21T17:04:37.592Z info:    Fee token: native
2025-10-21T17:04:38.579Z info: 💰 Estimated fees: 12327130238457656
2025-10-21T17:04:38.837Z info: Approving 100000000000000000000 tokens for router 0xF694E193200268f9a4868e4Aa017A0118C9a8177
2025-10-21T17:04:40.936Z info:    Waiting for 2 confirmation(s)...
2025-10-21T17:04:50.174Z info: 💰 Estimated CCIP fees: 12327130238457656
2025-10-21T17:04:50.174Z info: Sending CCIP message...
2025-10-21T17:04:51.485Z info: ⏳ CCIP message tx: 0xcc1e4371129d62e3bff8c2325f236298f64007c7fb6c12bf38b65b88c6791c75
2025-10-21T17:04:51.485Z info:    Waiting for 2 confirmation(s)...
2025-10-21T17:05:00.696Z info: ✅ CCIP message sent successfully
2025-10-21T17:05:00.697Z info:    Transaction: 0xcc1e4371129d62e3bff8c2325f236298f64007c7fb6c12bf38b65b88c6791c75
2025-10-21T17:05:00.697Z info:    Check status: https://ccip.chain.link/tx/0xcc1e4371129d62e3bff8c2325f236298f64007c7fb6c12bf38b65b88c6791c75
2025-10-21T17:05:00.697Z info: 📋 Transfer Summary:
2025-10-21T17:05:00.697Z info:    Token: 0xb613B55897F07eAF430bF9a509498e55487305Ea
2025-10-21T17:05:00.697Z info:    Amount: 100000000000000000000
2025-10-21T17:05:00.697Z info:    From: avalancheFuji
2025-10-21T17:05:00.697Z info:    To: ethereumSepolia
2025-10-21T17:05:00.697Z info:    Receiver: 0x27d7A69C878F9c8f51f4e53703abCE9bAcd2D9bf
2025-10-21T17:05:00.697Z info:    Fee paid in: native

Get the latest Chainlink content straight to your inbox.