|
| 1 | +--- |
| 2 | +section: ccip |
| 3 | +date: Last Modified |
| 4 | +title: "Configure Additional Networks using Foundry" |
| 5 | +metadata: |
| 6 | + description: "Learn how to configure additional networks in the smart-contract-examples repository to add support for more CCIP-supported chains using Foundry." |
| 7 | + excerpt: "network configuration, Foundry, HelperConfig.sol, CCIP Directory, chain configuration, smart-contract-examples" |
| 8 | + image: "/images/ccip/basic-architecture.png" |
| 9 | + datePublished: "2024-10-29" |
| 10 | + lastModified: "2025-10-24" |
| 11 | + estimatedTime: "10 minutes" |
| 12 | + difficulty: "beginner" |
| 13 | +--- |
| 14 | + |
| 15 | +import { Aside, CopyText, PageTabs } from "@components" |
| 16 | + |
| 17 | +<PageTabs |
| 18 | + pages={[ |
| 19 | + { |
| 20 | + name: "Hardhat", |
| 21 | + url: "/ccip/tutorials/evm/cross-chain-tokens/configure-additional-networks-hardhat", |
| 22 | + icon: "/images/tutorial-icons/hardhat-icn.png", |
| 23 | + }, |
| 24 | + { |
| 25 | + name: "Foundry", |
| 26 | + url: "/ccip/tutorials/evm/cross-chain-tokens/configure-additional-networks-foundry", |
| 27 | + icon: "/images/tutorial-icons/foundry-icn.png", |
| 28 | + }, |
| 29 | + ]} |
| 30 | +/> |
| 31 | + |
| 32 | +When working with the [smart-contract-examples](https://github.com/smartcontractkit/smart-contract-examples/tree/main/ccip/cct) CCIP tutorials, you may need to add support for additional blockchain networks beyond the default testnet configurations (_Avalanche Fuji_, _Ethereum Sepolia_, _Arbitrum Sepolia_, _Base Sepolia_, and _Polygon Amoy_). This guide explains how to update the network configuration files in the Foundry version of the repository. |
| 33 | + |
| 34 | +## Overview |
| 35 | + |
| 36 | +The [smart-contract-examples](https://github.com/smartcontractkit/smart-contract-examples/tree/main/ccip/cct/foundry) repository includes pre-configured network settings for common CCIP testnets. These configuration files store network-specific information such as: |
| 37 | + |
| 38 | +- Chain selectors |
| 39 | +- Router addresses |
| 40 | +- RMN Proxy addresses |
| 41 | +- Token Admin Registry addresses |
| 42 | +- Registry Module Owner Custom addresses |
| 43 | +- LINK token addresses |
| 44 | +- Block confirmations |
| 45 | +- Native currency symbols |
| 46 | + |
| 47 | +**Default networks included**: |
| 48 | + |
| 49 | +- Avalanche Fuji |
| 50 | +- Ethereum Sepolia |
| 51 | +- Arbitrum Sepolia |
| 52 | +- Base Sepolia |
| 53 | +- Polygon Amoy |
| 54 | + |
| 55 | +These values vary by network and must be accurate for your CCIP transactions to work correctly. If you want to use additional networks (e.g., Optimism Sepolia, BNB Chain Testnet, or mainnet networks), you'll need to update the configuration files following this guide. |
| 56 | + |
| 57 | +## Finding Network Configuration Values |
| 58 | + |
| 59 | +All CCIP-supported networks and their configuration details are available in the **CCIP Directory**: |
| 60 | + |
| 61 | +- **Testnet networks**: [CCIP Directory - Testnet](/ccip/directory/testnet) |
| 62 | +- **Mainnet networks**: [CCIP Directory - Mainnet](/ccip/directory/mainnet) |
| 63 | + |
| 64 | +The CCIP Directory provides: |
| 65 | + |
| 66 | +- Chain selectors |
| 67 | +- Router contract addresses |
| 68 | +- RMN Proxy addresses |
| 69 | +- Token Admin Registry addresses |
| 70 | +- Registry Module Owner Custom addresses |
| 71 | +- LINK token addresses |
| 72 | + |
| 73 | +<Aside type="caution" title="Always Use Official Values"> |
| 74 | + Always retrieve configuration values from the official [CCIP Directory](/ccip/directory) to ensure accuracy. Using |
| 75 | + incorrect addresses or chain selectors will cause your transactions to fail. |
| 76 | +</Aside> |
| 77 | + |
| 78 | +## Updating Configuration Files |
| 79 | + |
| 80 | +In the smart-contract-examples repository, Foundry projects store network configuration in `script/HelperConfig.s.sol`. |
| 81 | + |
| 82 | +**File location**: [`smart-contract-examples/ccip/cct/foundry/script/HelperConfig.s.sol`](https://github.com/smartcontractkit/smart-contract-examples/blob/main/ccip/cct/foundry/script/HelperConfig.s.sol) |
| 83 | + |
| 84 | +**Example structure**: |
| 85 | + |
| 86 | +```solidity |
| 87 | +// SPDX-License-Identifier: MIT |
| 88 | +pragma solidity 0.8.24; |
| 89 | +
|
| 90 | +import {Script} from "forge-std/Script.sol"; |
| 91 | +
|
| 92 | +contract HelperConfig is Script { |
| 93 | + NetworkConfig public activeNetworkConfig; |
| 94 | +
|
| 95 | + struct NetworkConfig { |
| 96 | + uint64 chainSelector; |
| 97 | + address router; |
| 98 | + address rmnProxy; |
| 99 | + address tokenAdminRegistry; |
| 100 | + address registryModuleOwnerCustom; |
| 101 | + address link; |
| 102 | + uint256 confirmations; |
| 103 | + string nativeCurrencySymbol; |
| 104 | + } |
| 105 | +
|
| 106 | + constructor() { |
| 107 | + if (block.chainid == 11155111) { |
| 108 | + activeNetworkConfig = getEthereumSepoliaConfig(); |
| 109 | + } else if (block.chainid == 421614) { |
| 110 | + activeNetworkConfig = getArbitrumSepolia(); |
| 111 | + } else if (block.chainid == 43113) { |
| 112 | + activeNetworkConfig = getAvalancheFujiConfig(); |
| 113 | + } else if (block.chainid == 84532) { |
| 114 | + activeNetworkConfig = getBaseSepoliaConfig(); |
| 115 | + } |
| 116 | + } |
| 117 | +
|
| 118 | + function getAvalancheFujiConfig() public pure returns (NetworkConfig memory) { |
| 119 | + NetworkConfig memory avalancheFujiConfig = NetworkConfig({ |
| 120 | + chainSelector: 14767482510784806043, |
| 121 | + router: 0xF694E193200268f9a4868e4Aa017A0118C9a8177, |
| 122 | + rmnProxy: 0xAc8CFc3762a979628334a0E4C1026244498E821b, |
| 123 | + tokenAdminRegistry: 0xA92053a4a3922084d992fD2835bdBa4caC6877e6, |
| 124 | + registryModuleOwnerCustom: 0x97300785aF1edE1343DB6d90706A35CF14aA3d81, |
| 125 | + link: 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846, |
| 126 | + confirmations: 2, |
| 127 | + nativeCurrencySymbol: "AVAX" |
| 128 | + }); |
| 129 | + return avalancheFujiConfig; |
| 130 | + } |
| 131 | +
|
| 132 | + // Add more network configurations here... |
| 133 | +} |
| 134 | +``` |
| 135 | + |
| 136 | +**Steps to add a new network**: |
| 137 | + |
| 138 | +1. Navigate to your cloned repository directory: |
| 139 | + |
| 140 | + ```bash |
| 141 | + cd smart-contract-examples/ccip/cct/foundry |
| 142 | + ``` |
| 143 | + |
| 144 | +1. Open `script/HelperConfig.s.sol` in your preferred editor |
| 145 | + |
| 146 | +1. Visit the [CCIP Directory](/ccip/directory/testnet) (for testnet) or [Mainnet Directory](/ccip/directory/mainnet) (for mainnet) |
| 147 | + |
| 148 | +1. Locate your desired network in the directory and copy the following values: |
| 149 | + - Chain Selector |
| 150 | + - Router address |
| 151 | + - RMN Proxy address |
| 152 | + - Token Admin Registry address |
| 153 | + - Registry Module Owner Custom address |
| 154 | + - LINK token address |
| 155 | + |
| 156 | +1. Find the network's chain ID from its official documentation |
| 157 | + |
| 158 | +1. Add a new condition in the `constructor()` to detect the chain ID |
| 159 | + |
| 160 | +1. Create a new function (e.g., `getOptimismSepoliaConfig()`) following the existing pattern |
| 161 | + |
| 162 | +1. Set appropriate values for: |
| 163 | + - `confirmations`: Number of block confirmations to wait (typically 2-3 for testnets, 5-10 for mainnet) |
| 164 | + - `nativeCurrencySymbol`: The native currency symbol (e.g., "ETH", "AVAX", "POL") |
| 165 | + |
| 166 | +1. Save the file and test your configuration with a simple script |
| 167 | + |
| 168 | +**Example: Adding Optimism Sepolia Testnet**: |
| 169 | + |
| 170 | +```solidity |
| 171 | +constructor() { |
| 172 | + if (block.chainid == 11155111) { |
| 173 | + activeNetworkConfig = getEthereumSepoliaConfig(); |
| 174 | + } else if (block.chainid == 421614) { |
| 175 | + activeNetworkConfig = getArbitrumSepolia(); |
| 176 | + } else if (block.chainid == 43113) { |
| 177 | + activeNetworkConfig = getAvalancheFujiConfig(); |
| 178 | + } else if (block.chainid == 84532) { |
| 179 | + activeNetworkConfig = getBaseSepoliaConfig(); |
| 180 | + } else if (block.chainid == 11155420) { |
| 181 | + activeNetworkConfig = getOptimismSepoliaConfig(); |
| 182 | + } |
| 183 | +} |
| 184 | +
|
| 185 | +function getOptimismSepoliaConfig() public pure returns (NetworkConfig memory) { |
| 186 | + NetworkConfig memory optimismSepoliaConfig = NetworkConfig({ |
| 187 | + chainSelector: 5224473277236331295, |
| 188 | + router: 0x114A20A10b43D4115e5aeef7345a1A71d2a60C57, |
| 189 | + rmnProxy: 0xb40A3109075965cc09E93719e33E748abf680dAe, |
| 190 | + tokenAdminRegistry: 0x1d702b1FA12F347f0921C722f9D9166F00DEB67A, |
| 191 | + registryModuleOwnerCustom: 0x49c4ba01dc6F5090f9df43Ab8F79449Db91A0CBB, |
| 192 | + link: 0xE4aB69C077896252FAFBD49EFD26B5D171A32410, |
| 193 | + confirmations: 2, |
| 194 | + nativeCurrencySymbol: "ETH" |
| 195 | + }); |
| 196 | + return optimismSepoliaConfig; |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +## Verifying Your Configuration |
| 201 | + |
| 202 | +After updating your configuration files, verify that: |
| 203 | + |
| 204 | +1. **Chain Selector**: Matches the value in the CCIP Directory |
| 205 | +1. **Router Address**: Matches the CCIP Router address for your network |
| 206 | +1. **RMN Proxy**: Matches the RMN Proxy address |
| 207 | +1. **Token Admin Registry**: Matches the registry address |
| 208 | +1. **Registry Module Owner Custom**: Matches the registry module address |
| 209 | +1. **LINK Token**: Matches the LINK token address for your network |
| 210 | +1. **Chain ID**: Correct for your network |
| 211 | +1. **Block Confirmations**: Set to a reasonable value (2-3 for testnets, higher for mainnet) |
| 212 | + |
| 213 | +<Aside type="caution" title="Test Before Production"> |
| 214 | + Always test your configuration on testnet before deploying to mainnet. Incorrect configuration values can result in |
| 215 | + failed transactions or loss of funds. |
| 216 | +</Aside> |
| 217 | + |
| 218 | +## Common Configuration Errors |
| 219 | + |
| 220 | +### Incorrect Chain Selector |
| 221 | + |
| 222 | +**Symptom**: Transactions fail with "destination chain not supported" error |
| 223 | +**Solution**: Verify the chain selector matches the CCIP Directory exactly |
| 224 | + |
| 225 | +### Wrong Router Address |
| 226 | + |
| 227 | +**Symptom**: Transactions revert when calling CCIP Router |
| 228 | +**Solution**: Ensure you're using the correct CCIP Router address from the directory |
| 229 | + |
| 230 | +### Mismatched Token Addresses |
| 231 | + |
| 232 | +**Symptom**: LINK approval or transfer operations fail |
| 233 | +**Solution**: Verify the LINK token address for your specific network |
| 234 | + |
| 235 | +### Chain ID Mismatch |
| 236 | + |
| 237 | +**Symptom**: Wrong network configuration is loaded |
| 238 | +**Solution**: Check that the chain ID in the constructor matches your target network |
| 239 | + |
| 240 | +## Related Resources |
| 241 | + |
| 242 | +- [CCIP Directory - Testnet](/ccip/directory/testnet): Complete list of testnet networks and configuration values |
| 243 | +- [CCIP Directory - Mainnet](/ccip/directory/mainnet): Complete list of mainnet networks and configuration values |
| 244 | +- [Register from an EOA (Burn & Mint)](/ccip/tutorials/evm/cross-chain-tokens/register-from-eoa-burn-mint-foundry): Tutorial using these configuration files |
| 245 | +- [Set Token Pool rate limits](/ccip/tutorials/evm/cross-chain-tokens/update-rate-limiters-foundry): Tutorial for configuring rate limiters |
| 246 | + |
| 247 | +## Adapting for Your Own Projects |
| 248 | + |
| 249 | +While this guide focuses on the smart-contract-examples repository structure, you can adapt these principles for your own projects: |
| 250 | + |
| 251 | +1. **Different project structure**: Adjust the file paths to match your project's organization |
| 252 | +1. **Custom configuration format**: You may use environment variables, YAML, TOML, or other formats—apply the same CCIP Directory values |
| 253 | +1. **Additional parameters**: Your project may require extra configuration fields beyond what's shown here |
| 254 | +1. **Multiple networks**: Consider organizing configurations by environment (development, staging, production) |
| 255 | + |
| 256 | +The key principle remains the same: **Always retrieve official CCIP configuration values from the [CCIP Directory](/ccip/directory)** to ensure compatibility and correctness. |
| 257 | + |
| 258 | +## Next Steps |
| 259 | + |
| 260 | +Once you've updated your network configuration in the smart-contract-examples repository: |
| 261 | + |
| 262 | +1. **Update RPC URLs**: Add the RPC URL to your `.env` file and use the environment variable as the value for the `--rpc-url` flag |
| 263 | + |
| 264 | +1. **Fund your wallet** with native tokens and LINK for the new network using the [Chainlink faucets](https://faucets.chain.link/) (for testnets) |
| 265 | + |
| 266 | +1. **Test the configuration** by running a simple deployment: |
| 267 | + |
| 268 | + ```bash |
| 269 | + forge script script/DeployToken.s.sol --rpc-url $YOUR_NEW_NETWORK_RPC_URL --private-key $PRIVATE_KEY --broadcast |
| 270 | + ``` |
| 271 | + |
| 272 | +1. **Follow the tutorials** using your newly configured network |
0 commit comments