diff --git a/ccip/token-transfer-using-arbitrary-messaging/README.md b/ccip/token-transfer-using-arbitrary-messaging/README.md index fa197a5..c8900dd 100644 --- a/ccip/token-transfer-using-arbitrary-messaging/README.md +++ b/ccip/token-transfer-using-arbitrary-messaging/README.md @@ -211,46 +211,161 @@ forge test ### Deploy Contracts -First, deploy the contracts to the specified networks. This script will: +This project uses a reliable split deployment architecture that eliminates RPC reliability issues. Deployment consists of two phases: -1. Deploy Bridge, Configuration, Token Pool, and Token contracts to all three networks -1. Configure cross-chain relationships between the contracts -1. Save all deployed contract addresses to `addresses.json` for use by the test scripts +#### Phase 1: Deploy Contracts (Independent) + +Deploy contracts to each chain independently. These commands use separate RPC endpoints and can run in parallel: ```sh -forge script script/Deploy.s.sol --broadcast --legacy --with-gas-price 100000000000 +# Deploy to Sepolia +forge script script/deploy/DeploySepolia.s.sol --broadcast + +# Deploy to Arbitrum Sepolia +forge script script/deploy/DeployArbitrumSepolia.s.sol --broadcast + +# Deploy to Fuji +forge script script/deploy/DeployFuji.s.sol --broadcast ``` -**Note**: The `addresses.json` file in this repository contains pre-deployed contract addresses from a previous deployment. When you run the deployment script above, it will overwrite this file with your new contract addresses. +#### Phase 2: Configure Cross-Chain Relationships (Independent) + +After ALL deployments complete successfully, configure cross-chain relationships: + +```sh +# Configure Sepolia +forge script script/configure/ConfigureSepolia.s.sol --broadcast + +# Configure Arbitrum Sepolia +forge script script/configure/ConfigureArbitrumSepolia.s.sol --broadcast + +# Configure Fuji +forge script script/configure/ConfigureFuji.s.sol --broadcast +``` + +#### Benefits of Split Deployment + +- **RPC Reliability**: Each script uses its own RPC endpoint, eliminating multi-RPC failures +- **Error Recovery**: Retry individual failed deployments without affecting successful ones +- **Parallel Execution**: Deploy to multiple chains simultaneously +- **Better Debugging**: Smaller, focused scripts are easier to troubleshoot -### Test Cross-Chain Token Transfers +**Note**: Each deployment creates a network-specific address file (`script/addresses-Sepolia.json`, `script/addresses-ArbitrumSepolia.json`, `script/addresses-Fuji.json`) with the deployed contract addresses. This ensures deployments don't overwrite each other and provides better error isolation. -After deployment, you can test different token transfer scenarios. Each test script reads the contract addresses from the `addresses.json` file created by the deployment. +## Test Cross-Chain Token Transfers -### Burn and Mint from Avalanche Fuji to Ethereum Sepolia +After deployment, test the complete token transfer ecosystem. Each script demonstrates a different mechanism and automatically reads contract addresses from network-specific files. -This script tests the burn and mint functionality, transferring tokens from Fuji to Sepolia. +### Overview of Transfer Mechanisms + +| Script | Source → Destination | Mechanism | Purpose | +| ---------------------- | -------------------- | -------------- | ----------------------- | +| `BurnAndMint.s.sol` | Fuji → Sepolia | Burn → Mint | Independent token pools | +| `LockAndMint.s.sol` | Sepolia → Arbitrum | Lock → Mint | Token bridging (step 1) | +| `BurnAndRelease.s.sol` | Arbitrum → Sepolia | Burn → Release | Token bridging (step 2) | + +--- + +### 1. Burn and Mint: Fuji → Sepolia + +This script demonstrates the burn and mint functionality by transferring tokens from Avalanche Fuji to Ethereum Sepolia. The script automatically reads deployed contract addresses from `addresses-Fuji.json`. + +**Command:** ```sh -forge script script/BurnAndMint.s.sol --broadcast --legacy --with-gas-price 100000000000 -vvvvv +forge script script/BurnAndMint.s.sol --broadcast --with-gas-price 100000000000 -vvvvv ``` -### Lock and Mint from Ethereum Sepolia to Arbitrum Sepolia +**Execution Flow:** + +1. **Setup**: Reads `addresses-Fuji.json` → Grants minter role → Mints 1000 test tokens +2. **Transfer**: Calculates fees → Approves tokens → Calls bridge transfer +3. **Cross-Chain**: Burns tokens on Fuji → Sends CCIP message → Mints on Sepolia + +**Key Details:** + +- **Networks**: Avalanche Fuji → Ethereum Sepolia +- **Amount**: 1000 burn/mint tokens +- **CCIP Fees**: ~0.023 LINK +- **Gas Used**: ~360,104 + +**Success Indicators:** + +- ✅ Message ID: `0x02f9b78cec831e4c548de955aa447057e8c93d635dac3eb96f2e8e21a03e4335` +- ✅ Events: `Burned`, `TokensTransferred`, `CrossChainMessageSent` +- ✅ [Track on CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x02f9b78cec831e4c548de955aa447057e8c93d635dac3eb96f2e8e21a03e4335) -This script tests the lock and mint functionality, transferring tokens from Sepolia to Arbitrum. +### 2. Lock and Mint: Sepolia → Arbitrum + +This script demonstrates the lock and mint functionality by transferring tokens from Ethereum Sepolia to Arbitrum Sepolia. The script automatically reads deployed contract addresses from `addresses-Sepolia.json`. + +**Command:** ```sh -forge script script/LockAndMint.s.sol --broadcast --legacy --with-gas-price 100000000000 -vvvvv +forge script script/LockAndMint.s.sol --broadcast --with-gas-price 100000000000 -vvvvv ``` -### Burn and Release from Arbitrum Sepolia to Ethereum Sepolia +**Execution Flow:** + +1. **Setup**: Reads `addresses-Sepolia.json` → Calculates fees → Approves tokens +2. **Transfer**: Transfers tokens to pool → Locks tokens → Calls bridge transfer +3. **Cross-Chain**: Sends CCIP message → Arbitrum receives → Mints equivalent tokens + +**Key Details:** + +- **Networks**: Ethereum Sepolia → Arbitrum Sepolia +- **Amount**: 1000 lockable tokens +- **CCIP Fees**: ~0.041 LINK +- **Gas Used**: ~325,384 -This script tests the burn and release functionality, transferring tokens from Arbitrum to Sepolia. +**Success Indicators:** + +- ✅ Message ID: `0xab14c3e93c2370e736c892d640dad06cc550ce4e277afe3c17af5c631a7491bf` +- ✅ Events: `Locked`, `TokensTransferred`, `CrossChainMessageSent` +- ✅ [Track on CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0xab14c3e93c2370e736c892d640dad06cc550ce4e277afe3c17af5c631a7491bf) + +### 3. Burn and Release: Arbitrum → Sepolia + +This script demonstrates the burn and release functionality by transferring tokens from Arbitrum Sepolia back to Ethereum Sepolia. The script automatically reads deployed contract addresses from `addresses-ArbitrumSepolia.json`. + +**Command:** ```sh -forge script script/BurnAndRelease.s.sol --broadcast --legacy --with-gas-price 100000000000 -vvvvv +forge script script/BurnAndRelease.s.sol --broadcast --with-gas-price 100000000000 -vvvvv ``` +**Execution Flow:** + +1. **Setup**: Reads `addresses-ArbitrumSepolia.json` → Grants minter role → Mints 1000 test tokens +2. **Transfer**: Calculates fees → Approves tokens → Calls bridge transfer +3. **Cross-Chain**: Burns tokens on Arbitrum → Sends CCIP message → Releases locked tokens on Sepolia + +**Key Details:** + +- **Networks**: Arbitrum Sepolia → Ethereum Sepolia +- **Amount**: 1000 burn/mint tokens +- **CCIP Fees**: ~0.024 LINK +- **Gas Used**: ~364,682 + +**Success Indicators:** + +- ✅ Message ID: `0x8679ffccc5f4f47bea12666d7e10fe514ea0e28de50dc5b978da1fabbbb0fa42` +- ✅ Events: `Burned`, `TokensTransferred`, `CrossChainMessageSent` +- ✅ [Track on CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x8679ffccc5f4f47bea12666d7e10fe514ea0e28de50dc5b978da1fabbbb0fa42) + +--- + +### Token Bridging Cycle + +The **Lock and Mint** + **Burn and Release** scripts demonstrate a complete token bridging cycle: + +| Step | Action | Result | +| ---- | ----------------------------------------- | ------------------------------------------------------------ | +| 1️⃣ | **Lock and Mint** (Sepolia → Arbitrum) | Tokens locked on Sepolia, equivalent minted on Arbitrum | +| 2️⃣ | **Burn and Release** (Arbitrum → Sepolia) | Tokens burned on Arbitrum, locked tokens released on Sepolia | + +This creates a **round-trip token bridging system** where the original tokens can be recovered. + ## Tracking Cross-Chain Transactions After running any of the test scripts, you can track the progress of your cross-chain token transfer using the transaction logs and the [Chainlink CCIP Explorer](https://ccip.chain.link/). diff --git a/ccip/token-transfer-using-arbitrary-messaging/foundry.toml b/ccip/token-transfer-using-arbitrary-messaging/foundry.toml index be6fa57..17def03 100644 --- a/ccip/token-transfer-using-arbitrary-messaging/foundry.toml +++ b/ccip/token-transfer-using-arbitrary-messaging/foundry.toml @@ -2,7 +2,11 @@ src = "src" out = "out" libs = ["lib", "node_modules"] -fs_permissions = [{ access = "read-write", path = "./script/addresses.json"}] +fs_permissions = [ + { access = "read-write", path = "./script/addresses-Sepolia.json"}, + { access = "read-write", path = "./script/addresses-ArbitrumSepolia.json"}, + { access = "read-write", path = "./script/addresses-Fuji.json"} +] remappings = [ "@chainlink/contracts/=node_modules/@chainlink/contracts/", "@chainlink/contracts-ccip/contracts/=node_modules/@chainlink/contracts-ccip/contracts/", diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/BaseConfiguration.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/BaseConfiguration.s.sol new file mode 100644 index 0000000..3b2ee88 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/BaseConfiguration.s.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {Script, console, stdJson} from "forge-std/Script.sol"; +import {Configuration} from "../src/bridge/Configuration.sol"; +import {MockERC20} from "../test/mocks/MockERC20.sol"; +import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {BaseDeployment} from "./BaseDeployment.s.sol"; + +abstract contract BaseConfiguration is BaseDeployment { + using stdJson for string; + + struct NetworkAddresses { + address bridge; + address configuration; + address lockReleasePool; + address burnMintPool; + address lockableToken; + address burnMintToken; + } + + struct ChainInfo { + uint64 chainSelector; + NetworkAddresses addresses; + } + + function loadNetworkAddresses(string memory networkName) internal view returns (NetworkAddresses memory) { + string memory fileName = string(abi.encodePacked("./script/addresses-", networkName, ".json")); + string memory json = vm.readFile(fileName); + + return NetworkAddresses({ + bridge: json.readAddress(".bridge"), + configuration: json.readAddress(".configuration"), + lockReleasePool: json.readAddress(".lockReleasePool"), + burnMintPool: json.readAddress(".burnMintPool"), + lockableToken: json.readAddress(".lockableToken"), + burnMintToken: json.readAddress(".burnMintToken") + }); + } + + function getAllChainInfo() internal view returns (ChainInfo[3] memory) { + ChainInfo[3] memory chains; + + // Sepolia - use getNetworkConfig for chain selector + chains[0] = ChainInfo({ + chainSelector: getNetworkConfig("Sepolia").chainSelector, + addresses: loadNetworkAddresses("Sepolia") + }); + + // ArbitrumSepolia - use getNetworkConfig for chain selector + chains[1] = ChainInfo({ + chainSelector: getNetworkConfig("ArbitrumSepolia").chainSelector, + addresses: loadNetworkAddresses("ArbitrumSepolia") + }); + + // Fuji - use getNetworkConfig for chain selector + chains[2] = ChainInfo({ + chainSelector: getNetworkConfig("Fuji").chainSelector, + addresses: loadNetworkAddresses("Fuji") + }); + + return chains; + } + + function setRemoteBridges( + Configuration configuration, + string memory currentNetworkName, + ChainInfo[3] memory allChains + ) internal { + // Get current chain selector from network config (single source of truth) + uint64 currentChainSelector = getNetworkConfig(currentNetworkName).chainSelector; + for (uint256 i = 0; i < allChains.length; i++) { + // Skip self + if (allChains[i].chainSelector != currentChainSelector) { + configuration.setRemoteBridge( + allChains[i].chainSelector, + allChains[i].addresses.bridge + ); + + configuration.setExtraArgs( + allChains[i].chainSelector, + Client._argsToBytes( + Client.GenericExtraArgsV2({ + gasLimit: 300_000, + allowOutOfOrderExecution: true + }) + ) + ); + } + } + } + + function configureSepoliaDestinationTokens( + Configuration sepoliaConfig, + ChainInfo[3] memory allChains + ) internal { + console.log("Setting destination tokens for Sepolia"); + + // Find indices for each chain + uint256 sepoliaIndex = 0; + uint256 arbitrumIndex = 1; + uint256 fujiIndex = 2; + + // Lock and Release with Fuji + sepoliaConfig.setDestinationToken( + MockERC20(allChains[sepoliaIndex].addresses.lockableToken), + allChains[fujiIndex].chainSelector, + MockERC20(allChains[fujiIndex].addresses.lockableToken) + ); + + // Burn and Mint with Fuji + sepoliaConfig.setDestinationToken( + IERC20(address(BurnMintERC20(allChains[sepoliaIndex].addresses.burnMintToken))), + allChains[fujiIndex].chainSelector, + IERC20(address(BurnMintERC20(allChains[fujiIndex].addresses.burnMintToken))) + ); + + // Lock and Mint with ArbitrumSepolia + sepoliaConfig.setDestinationToken( + IERC20(address(MockERC20(allChains[sepoliaIndex].addresses.lockableToken))), + allChains[arbitrumIndex].chainSelector, + IERC20(address(BurnMintERC20(allChains[arbitrumIndex].addresses.burnMintToken))) + ); + } + + function configureArbitrumSepoliaDestinationTokens( + Configuration arbitrumConfig, + ChainInfo[3] memory allChains + ) internal { + console.log("Setting destination tokens for ArbitrumSepolia"); + + // Find indices for each chain + uint256 sepoliaIndex = 0; + uint256 arbitrumIndex = 1; + + // Burn and Release with Sepolia + arbitrumConfig.setDestinationToken( + IERC20(address(BurnMintERC20(allChains[arbitrumIndex].addresses.burnMintToken))), + allChains[sepoliaIndex].chainSelector, + IERC20(address(MockERC20(allChains[sepoliaIndex].addresses.lockableToken))) + ); + } + + function configureFujiDestinationTokens( + Configuration fujiConfig, + ChainInfo[3] memory allChains + ) internal { + console.log("Setting destination tokens for Fuji"); + + // Find indices for each chain + uint256 sepoliaIndex = 0; + uint256 fujiIndex = 2; + + // Lock and Release with Sepolia + fujiConfig.setDestinationToken( + MockERC20(allChains[fujiIndex].addresses.lockableToken), + allChains[sepoliaIndex].chainSelector, + MockERC20(allChains[sepoliaIndex].addresses.lockableToken) + ); + + // Burn and Mint with Sepolia + fujiConfig.setDestinationToken( + IERC20(address(BurnMintERC20(allChains[fujiIndex].addresses.burnMintToken))), + allChains[sepoliaIndex].chainSelector, + IERC20(address(BurnMintERC20(allChains[sepoliaIndex].addresses.burnMintToken))) + ); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/BaseDeployment.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/BaseDeployment.s.sol new file mode 100644 index 0000000..7ff50d3 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/BaseDeployment.s.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {Script, console} from "forge-std/Script.sol"; +import {Bridge} from "../src/bridge/Bridge.sol"; +import {Configuration} from "../src/bridge/Configuration.sol"; +import {LockReleaseTokenPool} from "../src/pools/LockReleaseTokenPool.sol"; +import {BurnMintTokenPool} from "../src/pools/BurnMintTokenPool.sol"; +import {MockERC20} from "../test/mocks/MockERC20.sol"; +import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +abstract contract BaseDeployment is Script { + struct NetworkConfig { + string name; + uint64 chainSelector; + address router; + address link; + string rpcEnvVar; + } + + struct DeployedContracts { + Bridge bridge; + Configuration configuration; + LockReleaseTokenPool lockReleasePool; + BurnMintTokenPool burnMintPool; + MockERC20 lockableToken; + BurnMintERC20 burnMintToken; + } + + function deployNetworkContracts(NetworkConfig memory config) + internal + returns (DeployedContracts memory deployed) + { + // Deploy the lockable token (MockERC20) + deployed.lockableToken = new MockERC20( + string(abi.encodePacked("Mock Token ", config.name)), + "MTKlnu", + type(uint256).max + ); + + // Deploy the burn/mint token (BurnMintERC20) + deployed.burnMintToken = new BurnMintERC20( + string(abi.encodePacked("Mock Token ", config.name)), + "MTKbnm", + 18, + 0, // unlimited max supply + 0 // no premint + ); + + // Deploy configuration contract + deployed.configuration = new Configuration(); + + // Deploy bridge contract + deployed.bridge = new Bridge(config.router, deployed.configuration); + + // Deploy lock/release token pool + deployed.lockReleasePool = new LockReleaseTokenPool( + deployed.lockableToken, + address(deployed.bridge), + msg.sender + ); + + // Deploy burn/mint token pool + deployed.burnMintPool = new BurnMintTokenPool( + IERC20(address(deployed.burnMintToken)), + address(deployed.bridge) + ); + + // Grant minter and burner roles to the pool + deployed.burnMintToken.grantRole( + deployed.burnMintToken.MINTER_ROLE(), + address(deployed.burnMintPool) + ); + deployed.burnMintToken.grantRole( + deployed.burnMintToken.BURNER_ROLE(), + address(deployed.burnMintPool) + ); + + // Set token pools in configuration + deployed.configuration.setTokenPool(deployed.lockReleasePool); + deployed.configuration.setTokenPool(deployed.burnMintPool); + + return deployed; + } + + function logDeployedContracts(string memory networkName, DeployedContracts memory deployed) internal view { + console.log( + string(abi.encodePacked(networkName, " Bridge:")), + address(deployed.bridge) + ); + console.log( + string(abi.encodePacked(networkName, " LockReleasePool:")), + address(deployed.lockReleasePool) + ); + console.log( + string(abi.encodePacked(networkName, " BurnMintPool:")), + address(deployed.burnMintPool) + ); + console.log( + string(abi.encodePacked(networkName, " LockableToken:")), + address(deployed.lockableToken) + ); + console.log( + string(abi.encodePacked(networkName, " BurnMintToken:")), + address(deployed.burnMintToken) + ); + } + + function saveNetworkAddresses(string memory networkName, DeployedContracts memory deployed) internal { + string memory deployedContractsObj = string(abi.encodePacked(networkName, "Contracts")); + + vm.serializeAddress( + deployedContractsObj, + "bridge", + address(deployed.bridge) + ); + + vm.serializeAddress( + deployedContractsObj, + "configuration", + address(deployed.configuration) + ); + + vm.serializeAddress( + deployedContractsObj, + "lockReleasePool", + address(deployed.lockReleasePool) + ); + + vm.serializeAddress( + deployedContractsObj, + "burnMintPool", + address(deployed.burnMintPool) + ); + + vm.serializeAddress( + deployedContractsObj, + "lockableToken", + address(deployed.lockableToken) + ); + + string memory finalJson = vm.serializeAddress( + deployedContractsObj, + "burnMintToken", + address(deployed.burnMintToken) + ); + + // Save to network-specific JSON file + string memory fileName = string(abi.encodePacked("./script/addresses-", networkName, ".json")); + vm.writeJson(finalJson, fileName); + } + + function getNetworkConfig(string memory networkName) internal pure returns (NetworkConfig memory) { + if (keccak256(bytes(networkName)) == keccak256(bytes("Sepolia"))) { + return NetworkConfig({ + name: "Sepolia", + chainSelector: 16015286601757825753, + router: 0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59, + link: 0x779877A7B0D9E8603169DdbD7836e478b4624789, + rpcEnvVar: "ETHEREUM_SEPOLIA_RPC_URL" + }); + } else if (keccak256(bytes(networkName)) == keccak256(bytes("ArbitrumSepolia"))) { + return NetworkConfig({ + name: "ArbitrumSepolia", + chainSelector: 3478487238524512106, + router: 0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165, + link: 0xb1D4538B4571d411F07960EF2838Ce337FE1E80E, + rpcEnvVar: "ARBITRUM_SEPOLIA_RPC_URL" + }); + } else if (keccak256(bytes(networkName)) == keccak256(bytes("Fuji"))) { + return NetworkConfig({ + name: "Fuji", + chainSelector: 14767482510784806043, + router: 0xF694E193200268f9a4868e4Aa017A0118C9a8177, + link: 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846, + rpcEnvVar: "AVALANCHE_FUJI_RPC_URL" + }); + } else { + revert("Unknown network"); + } + } +} diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndMint.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndMint.s.sol index 9b55751..a4b2dda 100644 --- a/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndMint.s.sol +++ b/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndMint.s.sol @@ -21,10 +21,10 @@ contract TestBurnAndMintFromFujiToSepolia is Script { using stdJson for string; function run() external { - string memory json = vm.readFile("./script/addresses.json"); + string memory json = vm.readFile("./script/addresses-Fuji.json"); - address bridgeAddress = json.readAddress(".Fuji_bridge"); - address burnMintTokenAddress = json.readAddress(".Fuji_burnMintToken"); + address bridgeAddress = json.readAddress(".bridge"); + address burnMintTokenAddress = json.readAddress(".burnMintToken"); uint64 sepoliaChainSelector = 16015286601757825753; address linkTokenAddress = 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846; diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndRelease.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndRelease.s.sol index 537dff0..7e10fef 100644 --- a/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndRelease.s.sol +++ b/ccip/token-transfer-using-arbitrary-messaging/script/BurnAndRelease.s.sol @@ -30,12 +30,12 @@ contract TestBurnAndReleaseFromArbitrumToSepolia is Script { } function run() external { - string memory json = vm.readFile("./script/addresses.json"); + string memory json = vm.readFile("./script/addresses-ArbitrumSepolia.json"); NetworkDetails memory arbitrum = NetworkDetails({ - bridge: json.readAddress(".ArbitrumSepolia_bridge"), - burnMintPool: json.readAddress(".ArbitrumSepolia_burnMintPool"), - burnMintToken: json.readAddress(".ArbitrumSepolia_burnMintToken"), + bridge: json.readAddress(".bridge"), + burnMintPool: json.readAddress(".burnMintPool"), + burnMintToken: json.readAddress(".burnMintToken"), linkToken: 0xb1D4538B4571d411F07960EF2838Ce337FE1E80E, chainSelector: 16015286601757825753, rpcUrl: vm.envString("ARBITRUM_SEPOLIA_RPC_URL") diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/Deploy.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/Deploy.s.sol deleted file mode 100644 index 7c84f54..0000000 --- a/ccip/token-transfer-using-arbitrary-messaging/script/Deploy.s.sol +++ /dev/null @@ -1,286 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -/** - * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. - * Users are advised to thoroughly test and audit their own implementations - * before deploying to mainnet or any production environment. - * - * @dev This code is intended for educational and illustrative purposes only. - * Use it at your own risk. The authors are not responsible for any loss of - * funds or other damages caused by the use of this code. - */ - -import {Script, console} from "forge-std/Script.sol"; -import {Bridge} from "../src/bridge/Bridge.sol"; -import {Configuration} from "../src/bridge/Configuration.sol"; -import {LockReleaseTokenPool} from "../src/pools/LockReleaseTokenPool.sol"; -import {BurnMintTokenPool} from "../src/pools/BurnMintTokenPool.sol"; -import {MockERC20} from "../test/mocks/MockERC20.sol"; -import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; - -contract Deploy is Script { - struct NetworkDetails { - string name; - string rpcUrl; - uint256 fork; - uint64 chainSelector; - address router; - address link; - Bridge bridge; - Configuration configuration; - LockReleaseTokenPool lockReleasePool; - BurnMintTokenPool burnMintPool; - MockERC20 lockableToken; - BurnMintERC20 burnMintToken; - } - - function run() external { - NetworkDetails[] memory networks = new NetworkDetails[](3); - - // Ethereum Sepolia - networks[0] = NetworkDetails({ - name: "Sepolia", - rpcUrl: vm.envString("ETHEREUM_SEPOLIA_RPC_URL"), - fork: 0, - chainSelector: 16015286601757825753, - router: 0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59, - link: 0x779877A7B0D9E8603169DdbD7836e478b4624789, - bridge: Bridge(address(0)), - configuration: Configuration(address(0)), - lockReleasePool: LockReleaseTokenPool(address(0)), - burnMintPool: BurnMintTokenPool(address(0)), - lockableToken: MockERC20(address(0)), - burnMintToken: BurnMintERC20(address(0)) - }); - - // Arbitrum Sepolia - networks[1] = NetworkDetails({ - name: "ArbitrumSepolia", - rpcUrl: vm.envString("ARBITRUM_SEPOLIA_RPC_URL"), - fork: 0, - chainSelector: 3478487238524512106, - router: 0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165, - link: 0xb1D4538B4571d411F07960EF2838Ce337FE1E80E, - bridge: Bridge(address(0)), - configuration: Configuration(address(0)), - lockReleasePool: LockReleaseTokenPool(address(0)), - burnMintPool: BurnMintTokenPool(address(0)), - lockableToken: MockERC20(address(0)), - burnMintToken: BurnMintERC20(address(0)) - }); - - // Avalanche Fuji - networks[2] = NetworkDetails({ - name: "Fuji", - rpcUrl: vm.envString("AVALANCHE_FUJI_RPC_URL"), - fork: 0, - chainSelector: 14767482510784806043, - router: 0xF694E193200268f9a4868e4Aa017A0118C9a8177, - link: 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846, - bridge: Bridge(address(0)), - configuration: Configuration(address(0)), - lockReleasePool: LockReleaseTokenPool(address(0)), - burnMintPool: BurnMintTokenPool(address(0)), - lockableToken: MockERC20(address(0)), - burnMintToken: BurnMintERC20(address(0)) - }); - - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - - // Deploy contracts on each network - for (uint256 i = 0; i < networks.length; i++) { - NetworkDetails memory network = networks[i]; - network.fork = vm.createSelectFork(network.rpcUrl); - vm.startBroadcast(deployerPrivateKey); - - network.lockableToken = new MockERC20( - string(abi.encodePacked("Mock Token ", network.name)), - "MTKlnu", - type(uint256).max - ); - network.burnMintToken = new BurnMintERC20( - string(abi.encodePacked("Mock Token ", network.name)), - "MTKbnm", - 18, - 0, // unlimited max supply - 0 // no premint - ); - network.configuration = new Configuration(); - network.bridge = new Bridge(network.router, network.configuration); - network.lockReleasePool = new LockReleaseTokenPool( - network.lockableToken, - address(network.bridge), - msg.sender - ); - network.burnMintPool = new BurnMintTokenPool( - IERC20(address(network.burnMintToken)), - address(network.bridge) - ); - - // Grant minter and burner roles to the pool - network.burnMintToken.grantRole(network.burnMintToken.MINTER_ROLE(), address(network.burnMintPool)); - network.burnMintToken.grantRole(network.burnMintToken.BURNER_ROLE(), address(network.burnMintPool)); - - network.configuration.setTokenPool(network.lockReleasePool); - network.configuration.setTokenPool(network.burnMintPool); - - networks[i] = network; - - vm.stopBroadcast(); - - console.log( - string(abi.encodePacked(network.name, " Bridge:")), - address(network.bridge) - ); - console.log( - string(abi.encodePacked(network.name, " LockReleasePool:")), - address(network.lockReleasePool) - ); - console.log( - string(abi.encodePacked(network.name, " BurnMintPool:")), - address(network.burnMintPool) - ); - console.log( - string(abi.encodePacked(network.name, " LockableToken:")), - address(network.lockableToken) - ); - console.log( - string(abi.encodePacked(network.name, " BurnMintToken:")), - address(network.burnMintToken) - ); - } - - // Set remote bridges - for (uint256 i = 0; i < networks.length; i++) { - NetworkDetails memory network = networks[i]; - vm.selectFork(network.fork); - vm.startBroadcast(deployerPrivateKey); - - for (uint256 j = 0; j < networks.length; j++) { - if (i != j) { - network.configuration.setRemoteBridge( - networks[j].chainSelector, - address(networks[j].bridge) - ); - network.configuration.setExtraArgs( - networks[j].chainSelector, - Client._argsToBytes( - Client.GenericExtraArgsV2({ - gasLimit: 300_000, - allowOutOfOrderExecution: true - }) - ) - ); - } - } - - // Custom destination token to test different combination of token pools - - if (keccak256(bytes(network.name)) == keccak256(bytes("Fuji"))) { - console.log("Setting destination tokens for Fuji"); - Configuration(network.configuration).setDestinationToken( - MockERC20(network.lockableToken), - networks[0].chainSelector, - MockERC20(networks[0].lockableToken) // lock and Release with Sepolia - ); - Configuration(network.configuration).setDestinationToken( - IERC20(address(network.burnMintToken)), - networks[0].chainSelector, - IERC20(address(networks[0].burnMintToken)) // Burn and Mint with Sepolia - ); - } else if ( - keccak256(bytes(network.name)) == - keccak256(bytes("ArbitrumSepolia")) - ) { - console.log("Setting destination tokens for ArbitrumSepolia"); - Configuration(network.configuration).setDestinationToken( - IERC20(address(BurnMintERC20(network.burnMintToken))), - networks[0].chainSelector, - IERC20(address(MockERC20(networks[0].lockableToken))) - ); // Burn and Release with Sepolia - } else if ( - keccak256(bytes(network.name)) == keccak256(bytes("Sepolia")) - ) { - console.log("Setting destination tokens for Sepolia"); - Configuration(network.configuration).setDestinationToken( - MockERC20(network.lockableToken), - networks[2].chainSelector, - MockERC20(networks[2].lockableToken) - ); // lock and Release with Fuji - Configuration(network.configuration).setDestinationToken( - IERC20(address(BurnMintERC20(network.burnMintToken))), - networks[2].chainSelector, - IERC20(address(BurnMintERC20(networks[2].burnMintToken))) - ); // Burn and Mint with Fuji - Configuration(network.configuration).setDestinationToken( - IERC20(address(MockERC20(network.lockableToken))), - networks[1].chainSelector, - IERC20(address(BurnMintERC20(networks[1].burnMintToken))) - ); // lock and Mint with ArbitrumSepolia - } - - vm.stopBroadcast(); - - console.log( - string(abi.encodePacked(network.name, " remote bridges set")) - ); - } - // Save the addresses to a file - saveAddresses(networks); - } - - function saveAddresses(NetworkDetails[] memory networks) internal { - string memory deployedContractsObj = "deployedContracts"; - - for (uint256 i = 0; i < networks.length; i++) { - NetworkDetails memory network = networks[i]; - string memory networkName = network.name; - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_bridge")), - address(network.bridge) - ); - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_configuration")), - address(network.configuration) - ); - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_lockReleasePool")), - address(network.lockReleasePool) - ); - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_burnMintPool")), - address(network.burnMintPool) - ); - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_lockableToken")), - address(network.lockableToken) - ); - - vm.serializeAddress( - deployedContractsObj, - string(abi.encodePacked(networkName, "_burnMintToken")), - address(network.burnMintToken) - ); - } - - string memory finalJson = vm.serializeBool( - deployedContractsObj, - "completed", - true - ); - vm.writeJson(finalJson, "./script/addresses.json"); - } -} diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/LockAndMint.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/LockAndMint.s.sol index 85f871a..d759b8a 100644 --- a/ccip/token-transfer-using-arbitrary-messaging/script/LockAndMint.s.sol +++ b/ccip/token-transfer-using-arbitrary-messaging/script/LockAndMint.s.sol @@ -29,12 +29,12 @@ contract TestLockAndMintFromSepoliaToArbitrum is Script { } function run() external { - string memory json = vm.readFile("./script/addresses.json"); + string memory json = vm.readFile("./script/addresses-Sepolia.json"); NetworkDetails memory sepolia = NetworkDetails({ - bridge: json.readAddress(".Sepolia_bridge"), - lockReleasePool: json.readAddress(".Sepolia_lockReleasePool"), - lockableToken: json.readAddress(".Sepolia_lockableToken"), + bridge: json.readAddress(".bridge"), + lockReleasePool: json.readAddress(".lockReleasePool"), + lockableToken: json.readAddress(".lockableToken"), linkToken: 0x779877A7B0D9E8603169DdbD7836e478b4624789, chainSelector: 3478487238524512106, rpcUrl: vm.envString("ETHEREUM_SEPOLIA_RPC_URL") diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/addresses-ArbitrumSepolia.json b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-ArbitrumSepolia.json new file mode 100644 index 0000000..e1f427e --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-ArbitrumSepolia.json @@ -0,0 +1,8 @@ +{ + "bridge": "0x00f24d08Ea8B2B6a349d1B2eea029594f0dc11C1", + "burnMintPool": "0xB1A3AfE6cEE13648F00fC5f6d488E9441b0b486f", + "burnMintToken": "0x1967e4Bd2A8d969D896cF1eFbA058E6c78102AaF", + "configuration": "0x56Dd334beFe38265842028Ce1Eed49EC18252c03", + "lockReleasePool": "0x051738c4a83Bf23E20210025AFaD16b9004360B0", + "lockableToken": "0xb2a1E10ff2C794a34bb0D675AcdEF2C39C44366b" +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Fuji.json b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Fuji.json new file mode 100644 index 0000000..29730b6 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Fuji.json @@ -0,0 +1,8 @@ +{ + "bridge": "0xfa0682442Fc783aAb11D7A5ACaf991148e68209A", + "burnMintPool": "0x6d0CaD29a62e92220D34C73d3C7B4C9990a9F593", + "burnMintToken": "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9", + "configuration": "0x4f5f9Ba6D572B321d0048Ba451d4809D572c52Cd", + "lockReleasePool": "0x71728A0f396635546E7D75375b1884abE7623dE2", + "lockableToken": "0x6950cD5DC01B7570BFaa9bB7e489fF86Bb9F0F86" +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Sepolia.json b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Sepolia.json new file mode 100644 index 0000000..55317d9 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/addresses-Sepolia.json @@ -0,0 +1,8 @@ +{ + "bridge": "0x49a93323402212C4915E792a6B7D46b20C7eD9bE", + "burnMintPool": "0xFC9380779E5d21F52cc51c59369f8E936cDebB36", + "burnMintToken": "0x91b2b59aAc1d0053eCf67D180e8F2A2f79144e5a", + "configuration": "0xadd872ba1b8b556ECd0E412a8685e693B4A068cF", + "lockReleasePool": "0x5A748B81c221fDa976a03fF7E1f611278A8D44AA", + "lockableToken": "0x25a399d8A2e491C1812C8e124cE6A56f24bd3Cd9" +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/addresses.json b/ccip/token-transfer-using-arbitrary-messaging/script/addresses.json deleted file mode 100644 index 0bb64bb..0000000 --- a/ccip/token-transfer-using-arbitrary-messaging/script/addresses.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "ArbitrumSepolia_bridge": "0xe114197F0c20e65bCb20dc37653599AA9c572776", - "ArbitrumSepolia_burnMintPool": "0x0Ba199bD57d72dD9D50aC44B5ed0a797c2bdB630", - "ArbitrumSepolia_burnMintToken": "0xB74dC068486cEB67cbf9b62Ba10F0623FaFFD82D", - "ArbitrumSepolia_configuration": "0x0d49847017aB280e29725866630B375598f83a72", - "ArbitrumSepolia_lockReleasePool": "0x69e4531ddF6821Ac1d6DaBd63E5803130CA9D279", - "ArbitrumSepolia_lockableToken": "0xCd542b0C99092BDaDfEcc759eDef4136E6F42577", - "Fuji_bridge": "0x0178b1F8Eb54D469F8Ce2e24c554b64BD2fC5393", - "Fuji_burnMintPool": "0x95a66F64E5cCdC714474886AA0e228f40D6987C9", - "Fuji_burnMintToken": "0x41c619bd8539B04c89B305E4523B491E9a9d8aDE", - "Fuji_configuration": "0x01e588400d85672413c492433D4ac5140cC86a26", - "Fuji_lockReleasePool": "0x8524659a955169460B9DAA83833F91C625224ccB", - "Fuji_lockableToken": "0x2fc9C2e521Fa6e6893F4aB8dC7822568D4A4572C", - "Sepolia_bridge": "0x6DDE0d425f0eBde9747460360Ca63E06B93d1025", - "Sepolia_burnMintPool": "0xf5DA4735F1d81893074697e53BE2743a7a701157", - "Sepolia_burnMintToken": "0xB9bbeF3582D4726CF2611f931b3f3B0426C9526C", - "Sepolia_configuration": "0x29569AF3fb671972D8b9FAd83da44676a512dd76", - "Sepolia_lockReleasePool": "0x227e98E683c178d9096A7D8b6a5CA5bCd08c3749", - "Sepolia_lockableToken": "0x9a27B7268E29fc10B809C0921dFa86477886DC5B", - "completed": true -} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureArbitrumSepolia.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureArbitrumSepolia.s.sol new file mode 100644 index 0000000..2b030b4 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureArbitrumSepolia.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {Configuration} from "../../src/bridge/Configuration.sol"; +import {BaseConfiguration} from "../BaseConfiguration.s.sol"; +import {console} from "forge-std/console.sol"; + +contract ConfigureArbitrumSepolia is BaseConfiguration { + function run() external { + // Create fork for ArbitrumSepolia network + string memory rpcUrl = vm.envString("ARBITRUM_SEPOLIA_RPC_URL"); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Load all chain information from addresses.json + ChainInfo[3] memory allChains = getAllChainInfo(); + + // Get ArbitrumSepolia configuration contract + Configuration arbitrumConfig = Configuration(allChains[1].addresses.configuration); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Set remote bridges for other chains + setRemoteBridges(arbitrumConfig, "ArbitrumSepolia", allChains); + + // Configure destination tokens specific to ArbitrumSepolia + configureArbitrumSepoliaDestinationTokens(arbitrumConfig, allChains); + + // Stop broadcasting + vm.stopBroadcast(); + + console.log("ArbitrumSepolia remote bridges set"); + console.log("=== ArbitrumSepolia Configuration Complete ==="); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureFuji.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureFuji.s.sol new file mode 100644 index 0000000..4cbdde2 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureFuji.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {BaseConfiguration} from "../BaseConfiguration.s.sol"; +import {console} from "forge-std/console.sol"; +import {Configuration} from "../../src/bridge/Configuration.sol"; + +contract ConfigureFuji is BaseConfiguration { + function run() external { + // Create fork for Fuji network + string memory rpcUrl = vm.envString("AVALANCHE_FUJI_RPC_URL"); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Load all chain information from addresses.json + ChainInfo[3] memory allChains = getAllChainInfo(); + + // Get Fuji configuration contract + Configuration fujiConfig = Configuration(allChains[2].addresses.configuration); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Set remote bridges for other chains + setRemoteBridges(fujiConfig, "Fuji", allChains); + + // Configure destination tokens specific to Fuji + configureFujiDestinationTokens(fujiConfig, allChains); + + // Stop broadcasting + vm.stopBroadcast(); + + console.log("Fuji remote bridges set"); + console.log("=== Fuji Configuration Complete ==="); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureSepolia.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureSepolia.s.sol new file mode 100644 index 0000000..25da01a --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/configure/ConfigureSepolia.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {BaseConfiguration} from "../BaseConfiguration.s.sol"; +import {console} from "forge-std/console.sol"; +import {Configuration} from "../../src/bridge/Configuration.sol"; + +contract ConfigureSepolia is BaseConfiguration { + function run() external { + // Create fork for Sepolia network + string memory rpcUrl = vm.envString("ETHEREUM_SEPOLIA_RPC_URL"); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Load all chain information from addresses.json + ChainInfo[3] memory allChains = getAllChainInfo(); + + // Get Sepolia configuration contract + Configuration sepoliaConfig = Configuration(allChains[0].addresses.configuration); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Set remote bridges for other chains + setRemoteBridges(sepoliaConfig, "Sepolia", allChains); + + // Configure destination tokens specific to Sepolia + configureSepoliaDestinationTokens(sepoliaConfig, allChains); + + // Stop broadcasting + vm.stopBroadcast(); + + console.log("Sepolia remote bridges set"); + console.log("=== Sepolia Configuration Complete ==="); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployArbitrumSepolia.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployArbitrumSepolia.s.sol new file mode 100644 index 0000000..9613089 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployArbitrumSepolia.s.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {BaseDeployment} from "../BaseDeployment.s.sol"; +import {console} from "forge-std/console.sol"; + +contract DeployArbitrumSepolia is BaseDeployment { + function run() external { + // Get network configuration for ArbitrumSepolia + NetworkConfig memory config = getNetworkConfig("ArbitrumSepolia"); + + // Create fork for ArbitrumSepolia network + string memory rpcUrl = vm.envString(config.rpcEnvVar); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Deploy all contracts for ArbitrumSepolia + DeployedContracts memory deployed = deployNetworkContracts(config); + + // Stop broadcasting + vm.stopBroadcast(); + + // Log deployed contracts + logDeployedContracts(config.name, deployed); + + // Save addresses to JSON file + saveNetworkAddresses(config.name, deployed); + + console.log("=== ArbitrumSepolia Deployment Complete ==="); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployFuji.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployFuji.s.sol new file mode 100644 index 0000000..2a1f11c --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeployFuji.s.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {BaseDeployment} from "../BaseDeployment.s.sol"; +import {console} from "forge-std/console.sol"; + +contract DeployFuji is BaseDeployment { + function run() external { + // Get network configuration for Fuji + NetworkConfig memory config = getNetworkConfig("Fuji"); + + // Create fork for Fuji network + string memory rpcUrl = vm.envString(config.rpcEnvVar); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Deploy all contracts for Fuji + DeployedContracts memory deployed = deployNetworkContracts(config); + + // Stop broadcasting + vm.stopBroadcast(); + + // Log deployed contracts + logDeployedContracts(config.name, deployed); + + // Save addresses to JSON file + saveNetworkAddresses(config.name, deployed); + + console.log("=== Fuji Deployment Complete ==="); + } +} \ No newline at end of file diff --git a/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeploySepolia.s.sol b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeploySepolia.s.sol new file mode 100644 index 0000000..7f54db8 --- /dev/null +++ b/ccip/token-transfer-using-arbitrary-messaging/script/deploy/DeploySepolia.s.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/** + * @notice This contract is provided "AS IS" without warranties of any kind, as an example and has not been audited. + * Users are advised to thoroughly test and audit their own implementations + * before deploying to mainnet or any production environment. + * + * @dev This code is intended for educational and illustrative purposes only. + * Use it at your own risk. The authors are not responsible for any loss of + * funds or other damages caused by the use of this code. + */ + +import {BaseDeployment} from "../BaseDeployment.s.sol"; +import {console} from "forge-std/console.sol"; + +contract DeploySepolia is BaseDeployment { + function run() external { + // Get network configuration for Sepolia + NetworkConfig memory config = getNetworkConfig("Sepolia"); + + // Create fork for Sepolia network + string memory rpcUrl = vm.envString(config.rpcEnvVar); + vm.createSelectFork(rpcUrl); + + // Get deployer private key + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Start broadcasting transactions + vm.startBroadcast(deployerPrivateKey); + + // Deploy all contracts for Sepolia + DeployedContracts memory deployed = deployNetworkContracts(config); + + // Stop broadcasting + vm.stopBroadcast(); + + // Log deployed contracts + logDeployedContracts(config.name, deployed); + + // Save addresses to JSON file + saveNetworkAddresses(config.name, deployed); + + console.log("=== Sepolia Deployment Complete ==="); + } +}