# Enable your tokens in CCIP (Burn & Mint): Register from an EOA using Foundry
Source: https://docs.chain.link/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry
Last Updated: 2025-10-30

> For the complete documentation index, see [llms.txt](/llms.txt).

<PageTabs
  pages={[
  {
    name: "Hardhat (Burn & Mint)",
    url: "/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-hardhat",
    icon: "/images/tutorial-icons/hardhat-icn.png",
  },
  {
    name: "Foundry (Burn & Mint)",
    url: "/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry",
    icon: "/images/tutorial-icons/foundry-icn.png",
  },
]}
/>

This tutorial will guide you through the process of enabling your own tokens in CCIP using [Foundry](https://book.getfoundry.sh/). 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`](https://github.com/smartcontractkit/chainlink-evm/blob/contracts-solidity/1.5.0/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol) tokens on the Avalanche Fuji and Arbitrum Sepolia testnets.

2. **Deploying Token Pools**: Once your tokens are deployed, you will deploy [`BurnMintTokenPool`](/ccip/api-reference/evm/v1.6.1/burn-mint-token-pool) 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](https://github.com/smartcontractkit/chainlink-evm/blob/contracts-solidity/1.5.0/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol#L142) 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`](/ccip/api-reference/evm/v1.6.1/registry-module-owner-custom) contract's [`registerAdminViaOwner`](/ccip/api-reference/evm/v1.6.1/registry-module-owner-custom#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`](/ccip/api-reference/evm/v1.6.1/token-admin-registry) contract's [`acceptAdminRole`](/ccip/api-reference/evm/v1.6.1/token-admin-registry#acceptadminrole) function to complete the registration process.

5. **Linking Tokens to Pools**: You will call the [`TokenAdminRegistry`](/ccip/api-reference/evm/v1.6.1/token-admin-registry) contract's [`setPool`](/ccip/api-reference/evm/v1.6.1/token-admin-registry#setpool) function to associate each token with its respective token pool.

6. **Configuring Token Pools**: You will call the [`applyChainUpdates`](/ccip/api-reference/evm/v1.6.1/token-pool#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`](https://github.com/smartcontractkit/chainlink-evm/blob/contracts-solidity/1.5.0/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol#L128) 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](https://nodejs.org/en/download/) if you don't have it installed. Optionally, you can use the [nvm package](https://www.npmjs.com/package/nvm) to switch between Node.js versions:

   ```bash
   nvm use 22
   ```

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

   ```bash
   node -v
   ```

   Example output:

   ```bash
   $ node -v
   v22.15.0
   ```

2. **Install Foundry**:
   If you haven't already, follow the instructions in the [Foundry documentation](https://book.getfoundry.sh/getting-started/installation) to install Foundry.

3. **Clone the repository and navigate to the project directory**:

   ```bash
   git clone https://github.com/smartcontractkit/smart-contract-examples.git
   cd smart-contract-examples/ccip/cct/foundry
   ```

4. **Set up your environment**: Create a `.env` file by copying the `.env.example` file, and fill in the required values:

   ```bash
   cp .env.example .env
   ```

   Example `.env` file:

   ```bash
   PRIVATE_KEY=<your_private_key>
   RPC_URL_FUJI=<your_rpc_url_fuji>
   RPC_URL_ARBITRUM_SEPOLIA=<your_rpc_url_arbitrum_sepolia>
   ETHERSCAN_API_KEY=<your_etherscan_api_key>
   ```

   Variables to configure:

   - `PRIVATE_KEY`: The private key for your testnet wallet. If you use MetaMask, you can follow this [guide](https://support.metamask.io/managing-my-wallet/secret-recovery-phrase-and-private-keys/how-to-export-an-accounts-private-key/) to export your private key. **Note**: This key is required for signing transactions like token transfers.
   - `RPC_URL_FUJI`: The RPC URL for the Fuji testnet. You can get this from the [Alchemy](https://www.alchemy.com/) or [Infura](https://infura.io/) website.
   - `RPC_URL_ARBITRUM_SEPOLIA`: The RPC URL for the Arbitrum Sepolia testnet. You can get this from the [Alchemy](https://www.alchemy.com/) or [Infura](https://infura.io/) website.
   - `ETHERSCAN_API_KEY`: An API key from Etherscan to verify your contracts. You can obtain one from [Etherscan](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics).

5. **Load the environment variables** into the terminal session where you will run the commands:

   ```bash
   source .env
   ```

6. **Install dependencies**:

   ```bash
   forge install && npm install
   ```

7. **Compile the contracts**:

   ```bash
   forge compile
   ```

### Optional: Configure your `config.json` file

Before running the scripts, you can customize the `config.json` within the `script` folder to your needs.

- By default, this guide and the accompanying scripts are configured to work with Avalanche Fuji (chain ID `43113`) and Arbitrum Sepolia (chain ID `421614`). If you do not make any changes to the `config.json` file, you will mint your tokens on Avalanche Fuji and transfer them to Arbitrum Sepolia.

- If you wish to customize the token parameters such as the token name, symbol, decimals, amount to mint, or amount to transfer, you can modify these fields in the `config.json` file accordingly.

  **Note**: If you decide to change the chain IDs in the `remoteChains` section to use different networks, you will also need to update your `.env` file with the appropriate RPC URLs for those networks.

> **NOTE: Using Different Networks**
>
> This tutorial uses Avalanche Fuji and Arbitrum Sepolia by default. To test with other CCIP-supported networks, see
> [Add CCIP Networks for Cross-Chain Token
> Tutorials](/ccip/tutorials/evm/cross-chain-tokens/configure-additional-networks-foundry).

Example `config.json` file:

```json
{
  "BnMToken": {
    "name": "BnM KH",
    "symbol": "BnMkh",
    "decimals": 18,
    "maxSupply": 0,
    "preMint": 100000000000000000000,
    "ccipAdminAddress": "0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA"
  },
  "tokenAmountToMint": 1000000000000000000000,
  "tokenAmountToTransfer": 100000000000000000000,
  "feeType": "link",
  "remoteChains": {
    "43113": 421614,
    "421614": 43113
  }
}
```

The `config.json` file contains the following parameters:

| Field                   | Description                                                                                                                                                                                                                                                                                                                                              |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                  | The name of the token you are going to deploy. Replace `"BnM KH"` with your desired token name.                                                                                                                                                                                                                                                          |
| `symbol`                | The symbol of the token. Replace `"BnMkh"` with your desired token symbol.                                                                                                                                                                                                                                                                               |
| `decimals`              | The number of decimals for the token (usually `18` for standard ERC tokens).                                                                                                                                                                                                                                                                             |
| `maxSupply`             | The maximum supply of tokens (in the smallest unit, based on `decimals`). When `maxSupply` is 0, the supply is unlimited.                                                                                                                                                                                                                                |
| `preMint`               | The amount of tokens to be minted to the owner at the time of deployment, specified (in the smallest unit, based on `decimals`). When `preMint` is 0, no tokens will be minted to the owner during deployment.                                                                                                                                           |
| `ccipAdminAddress`      | The address of the CCIP admin. Replace the address value `0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA` with your token deployer account address.                                                                                                                                                                                                          |
| ---                     | -----                                                                                                                                                                                                                                                                                                                                                    |
| `tokenAmountToMint`     | The amount of tokens to mint when running the minting script. This value should be specified in wei (1 token with 18 decimals = `1000000000000000000` wei).                                                                                                                                                                                              |
| ---                     | -----                                                                                                                                                                                                                                                                                                                                                    |
| `tokenAmountToTransfer` | The amount of tokens to transfer when running the token transfer script. Specify the number of tokens you want to transfer across chains.                                                                                                                                                                                                                |
| ---                     | -----                                                                                                                                                                                                                                                                                                                                                    |
| `feeType`               | Defines the fee type for transferring tokens across chains. Options are `"link"` (for paying fees in LINK tokens) or `"native"` (for paying fees in native tokens).                                                                                                                                                                                      |
| ---                     | -----                                                                                                                                                                                                                                                                                                                                                    |
| `remoteChains`          | Defines the relationship between source and remote (destination) chain IDs. The keys in this object are the current chain IDs, and the values represent the corresponding remote chain. Example: `"43113": 421614` means that if you're running a script on Avalanche Fuji (chain ID `43113`), the remote chain is Arbitrum Sepolia (chain ID `421614`). |

## Tutorial

> **NOTE: Explore the Code**
>
> All Foundry scripts used in this tutorial are located in the `script/` directory of the repository. Each script is
> thoroughly commented and directly linked to a key step in the tutorial, making the code self-explanatory. Read the
> code and comments to gain a deeper understanding of the process or explore the implementation details.

### Deploy Tokens

In this step, you will use the `DeployToken.s.sol` script to deploy your tokens on two testnets, Avalanche Fuji and Arbitrum Sepolia.

The script reads the [`config.json` file](/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry#optional-configure-your-configjson-file) to get the token name, symbol, decimals, maximum supply, and pre-mint amount. Based on these configurations, it deploys the appropriate token contract and grants mint and burn roles to your EOA.

1. Deploy tokens on Avalanche Fuji:

   ```bash
   forge script script/DeployToken.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast --verify
   ```

   Example output:

   ```bash
   Deployed BurnMintERC20 at: 0x56e4CFf5009908D8d8C5Aac5479574f9aC66e145
   Granted mint and burn roles to: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Writing deployed token address to file: ./script/output/deployedToken_avalancheFuji.json
   ```

2. Deploy tokens on Arbitrum Sepolia:

   ```bash
   forge script script/DeployToken.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast --verify
   ```

   Example output:

   ```bash
   Deployed BurnMintERC20 at: 0x8E9A370Ff35E9A5C081818B5C9EcC3E3EA89396b
   Granted mint and burn roles to: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Writing deployed token address to file: ./script/output/deployedToken_arbitrumSepolia.json
   ```

### Deploy Token Pools

> **CAUTION: Understand Token Pool Requirements**
>
> Before deploying your token pools, make sure you understand the mandatory requirements for token pools and the gas
> limit restrictions. The `releaseOrMint` function and other operations (e.g., balance checks) must not exceed the
> **90,000** gas limit on the destination blockchain. Failure to meet these requirements can lead to [manual
> execution](/ccip/concepts/manual-execution). For more details, refer to the [Common
> Requirements](/ccip/concepts/cross-chain-token/evm/token-pools#common-requirements).

In this step, you will use the `DeployBurnMintTokenPool.s.sol` script to deploy Burn & Mint token pools for the tokens on both testnets, Avalanche Fuji and Arbitrum Sepolia and grant mint and burn roles to the token pools.

1. Deploy a Burn & Mint token pool for the deployed token on Avalanche Fuji:

   ```bash
   forge script script/DeployBurnMintTokenPool.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast --verify
   ```

   Example output:

   ```bash
   Burn & Mint token pool deployed to: 0xeB841acbc25549D4deB6Ed9401f3CbB529F3DC3e
   Granted mint and burn roles to token pool: 0xeB841acbc25549D4deB6Ed9401f3CbB529F3DC3e
   Writing deployed token pool address to file: ./script/output/deployedTokenPool_avalancheFuji.json
   ```

2. Deploy a Burn & Mint token pool for the deployed token on Arbitrum Sepolia:

   ```bash
   forge script script/DeployBurnMintTokenPool.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast --verify
   ```

   Example output:

   ```bash
   Burn & Mint token pool deployed to: 0x346e11C1a869b88A8033e40B18Efdc4eCD9FFd02
   Granted mint and burn roles to token pool: 0x346e11C1a869b88A8033e40B18Efdc4eCD9FFd02
   Writing deployed token pool address to file: ./script/output/deployedTokenPool_arbitrumSepolia.json
   ```

### Claim Admin Role

In this step, you will use the `ClaimAdmin.s.sol` script to register your EOA as the administrator for the deployed tokens on both Avalanche Fuji and Arbitrum Sepolia testnets. This process involves interacting with the `RegistryModuleOwnerCustom` contract to set up your EOA as the admin.

The script will claim the admin role using `getCCIPAdmin()` function and validate by comparing the returned value with the value of the `ccipAdminAddress` field of your [`config.json` file](/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry#optional-configure-your-configjson-file). So, make sure to replace the value of the `ccipAdminAddress` field with your EOA or token deployer account address.

1. Claim the Admin role for the token on Avalanche Fuji:

   ```bash
   forge script script/ClaimAdmin.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Current token admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Claiming admin of the token via getCCIPAdmin() for CCIP admin: 0x45C90FBb5acC1a5c156a401B56Fea55e69E7669d
   Admin claimed successfully for token: 0x56e4CFf5009908D8d8C5Aac5479574f9aC66e145
   ```

2. Claim the Admin role for the token on Arbitrum Sepolia:

   ```bash
   forge script script/ClaimAdmin.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Current token admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Claiming admin of the token via getCCIPAdmin() for CCIP admin: 0x45C90FBb5acC1a5c156a401B56Fea55e69E7669d
   Admin claimed successfully for token: 0x8E9A370Ff35E9A5C081818B5C9EcC3E3EA89396b
   ```

### Accept Admin Role

In this step, you will use the `AcceptAdminRole.s.sol` script to accept the admin role for the deployed tokens on both Avalanche Fuji and Arbitrum Sepolia testnets. Once you have claimed the role, accepting the role finalizes your control over the token administration.

1. Accept the admin role for the token on Avalanche Fuji:

   ```bash
   forge script script/AcceptAdminRole.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Accepted admin role for token: 0x56e4CFf5009908D8d8C5Aac5479574f9aC66e145
   ```

2. Accept the admin role for the token on Arbitrum Sepolia:

   ```bash
   forge script script/AcceptAdminRole.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Accepted admin role for token: 0x8E9A370Ff35E9A5C081818B5C9EcC3E3EA89396b
   ```

### Set Token Pool

In this step, you will use the `SetPool.s.sol` script to link each token with its respective token pool on both testnets.

1. Link the token to its respective token pool on Avalanche Fuji:

   ```bash
   forge script script/SetPool.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Setting pool for token: 0x56e4CFf5009908D8d8C5Aac5479574f9aC66e145
   New pool address: 0xeB841acbc25549D4deB6Ed9401f3CbB529F3DC3e
   Action performed by admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Pool set for token 0x56e4CFf5009908D8d8C5Aac5479574f9aC66e145 to 0xeB841acbc25549D4deB6Ed9401f3CbB529F3DC3e
   ```

2. Link the token to its respective token pool on Arbitrum Sepolia:

   ```bash
   forge script script/SetPool.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Setting pool for token: 0x8E9A370Ff35E9A5C081818B5C9EcC3E3EA89396b
   New pool address: 0x346e11C1a869b88A8033e40B18Efdc4eCD9FFd02
   Action performed by admin: 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
   Pool set for token 0x8E9A370Ff35E9A5C081818B5C9EcC3E3EA89396b to 0x346e11C1a869b88A8033e40B18Efdc4eCD9FFd02
   ```

### Configure Token Pools

In this step, you will use the `ApplyChainUpdates.s.sol` script to initialize the token pool configuration on each blockchain to enable cross-chain transfers between Avalanche Fuji and Arbitrum Sepolia. This involves linking the token pool on one blockchain to a corresponding pool on another blockchain, allowing cross-chain token transfers. You will interact with the `TokenPool` contract by calling the `applyChainUpdates()` function to set up cross-chain parameters and rate limits.

**Parameters used in pool configuration**:

- **Main Parameters**:

| Parameter                   | Description                                                                                           | Default     | Required |
| --------------------------- | ----------------------------------------------------------------------------------------------------- | ----------- | -------- |
| **`poolAddress`**           | The address of the token pool being configured on the current chain.                                  | N/A         | Yes      |
| **`chainSelectorRemovals`** | An array of chain selectors (identifiers) for which configurations should be removed.                 | Empty array | No       |
| **`chainUpdates`**          | An array of `ChainUpdate` structs, each containing configuration updates for a specific remote chain. | N/A         | Yes      |

- **`ChainUpdate` Struct Parameters:**

Each `ChainUpdate` struct in the `chainUpdates` array includes the following fields:

| Field                           | Description                                                                                                                                             | Required |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| **`remoteChainSelector`**       | The chain selector (identifier) of the remote blockchain to which this pool will be linked.                                                             | Yes      |
| **`remotePoolAddresses`**       | An array of addresses of the token pools on the remote blockchain, each encoded as bytes (`abi.encode(remotePoolAddress)`).                             | Yes      |
| **`remoteTokenAddress`**        | The address of the token on the remote blockchain, encoded as bytes (`abi.encode(remoteTokenAddress)`).                                                 | Yes      |
| **`outboundRateLimiterConfig`** | Configuration for outbound rate limiting (transfers from current chain to remote chain). This is a struct with fields: `isEnabled`, `capacity`, `rate`. | No       |
| **`inboundRateLimiterConfig`**  | Configuration for inbound rate limiting (transfers from remote chain to current chain). This is a struct with fields: `isEnabled`, `capacity`, `rate`.  | No       |

- **Fields within `outboundRateLimiterConfig` and `inboundRateLimiterConfig`:**

| Sub-Parameter   | Description                                                                                                        | Default | Required |
| --------------- | ------------------------------------------------------------------------------------------------------------------ | ------- | -------- |
| **`isEnabled`** | A flag indicating whether rate limiting is enabled (`true` or `false`).                                            | `false` | No       |
| **`capacity`**  | The maximum number of tokens allowed in the bucket for rate limiting. Applicable only if rate limiting is enabled. | `0`     | No       |
| **`rate`**      | The rate at which tokens are refilled into the bucket per second. Applicable only if rate limiting is enabled.     | `0`     | No       |

1. Configure the token pool on Avalanche Fuji:

   ```bash
   forge script script/ApplyChainUpdates.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Chain update applied to pool at address: 0xeB841acbc25549D4deB6Ed9401f3CbB529F3DC3e
   ```

2. Configure the token pool on Arbitrum Sepolia:

   ```bash
   forge script script/ApplyChainUpdates.s.sol --rpc-url $RPC_URL_ARBITRUM_SEPOLIA --private-key $PRIVATE_KEY --broadcast
   ```

   Example output:

   ```bash
   Chain update applied to pool at address: 0x346e11C1a869b88A8033e40B18Efdc4eCD9FFd02
   ```

### Mint Tokens

In this step, you will use the `MintTokens.s.sol` script to mint tokens to your Externally Owned Account (EOA) on Avalanche Fuji. Since you granted mint and burn privileges to your EOA during the token deployment in the first step, you are authorized to mint tokens for testing purposes. This ensures that your EOA has sufficient tokens to perform cross-chain transfers in the next step.

The script will read the amount to mint from the `tokenAmountToMint` field in your [`config.json` file](/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry#optional-configure-your-configjson-file) and call the `mint()` function of the `BurnMintERC20` token contract to mint the tokens to your EOA.

Mint tokens for your EOA on Avalanche Fuji:

```bash
forge script script/MintTokens.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
```

Example output:

```bash
Minting 1000000000000000000000 tokens to 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
Waiting for confirmations...
Minted 1000000000000000000000 tokens to 0x8C244f0B2164E6A3BED74ab429B0ebd661Bb14CA
Current balance of receiver is 1000000000000000000000 BnMkh
```

### Transfer Tokens Across Networks

In this step, you will use the `TransferTokens.s.sol` script to transfer tokens from Avalanche Fuji to Arbitrum Sepolia using CCIP. You can choose to pay CCIP fees using LINK tokens or the native gas token.

The scripts reads the `tokenAmountToTransfer`, the `feeType`, and the `destinationChainId` from your [`config.json` file](/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry#optional-configure-your-configjson-file). It prepares the transfer by approving the token transfer and estimating the CCIP fees based on your `feeType`. The script then calls the `ccipSend()` function on the `IRouterClient` contract to initiate the cross-chain transfer.

Transfer tokens from Avalanche Fuji to Arbitrum Sepolia:

```bash
forge script script/TransferTokens.s.sol --rpc-url $RPC_URL_FUJI --private-key $PRIVATE_KEY --broadcast
```

Example output:

```bash
Estimated fees: 22153771891999418
Message ID:
0x7097afbbf87e803653f0b4d116369f91a6118153d183f466f86f1080ee7dd578
Check status of the message at https://ccip.chain.link/msg/7097afbbf87e803653f0b4d116369f91a6118153d183f466f86f1080ee7dd578
```

You can check the status of the message on the [Chainlink CCIP Explorer](https://ccip.chain.link/) using the message ID provided in the output.

> **CAUTION: Educational Example Disclaimer**
>
> This page includes an educational example to use a Chainlink system, product, or service and is provided to
> demonstrate how to interact with Chainlink's systems, products, and services to integrate them into your own. This
> template is provided "AS IS" and "AS AVAILABLE" without warranties of any kind, it has not been audited, and it may be
> missing key checks or error handling to make the usage of the system, product or service more clear. Do not use the
> code in this example in a production environment without completing your own audits and application of best practices.
> Neither Chainlink Labs, the Chainlink Foundation, nor Chainlink node operators are responsible for unintended outputs
> that are generated due to errors in code.