Files
smom-dbis-138/script/DeployAll.s.sol
2026-03-02 12:14:09 -08:00

356 lines
14 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script, console} from "forge-std/Script.sol";
import {WETH} from "../contracts/tokens/WETH.sol";
import {WETH10} from "../contracts/tokens/WETH10.sol";
import {CCIPWETH9Bridge} from "../contracts/ccip/CCIPWETH9Bridge.sol";
import {CCIPWETH10Bridge} from "../contracts/ccip/CCIPWETH10Bridge.sol";
/**
* @title DeployAll - Canonical Multichain Deployment Script
* @notice Deploys all contracts (WETH9, WETH10, CCIP Bridges, CCIPLogger) to multiple chains
* @dev Chain-aware deployment that adapts to different network configurations
*
* Supported Chains:
* - Ethereum Mainnet (chainId 1): Only deploys CCIPLogger (other contracts already deployed)
* - Cronos (chainId 25): Deploys all contracts
* - BSC (chainId 56): Deploys all contracts
* - Polygon PoS (chainId 137): Deploys all contracts
* - Gnosis Chain (chainId 100): Deploys all contracts
* - Avalanche (chainId 43114): Deploys all contracts
* - Base (chainId 8453): Deploys all contracts
* - Arbitrum (chainId 42161): Deploys all contracts
* - Optimism (chainId 10): Deploys all contracts
*/
contract DeployAll is Script {
// Chain IDs
uint256 constant MAINNET = 1;
uint256 constant CRONOS = 25;
uint256 constant BSC = 56;
uint256 constant POLYGON = 137;
uint256 constant GNOSIS = 100;
uint256 constant AVALANCHE = 43114;
uint256 constant BASE = 8453;
uint256 constant ARBITRUM = 42161;
uint256 constant OPTIMISM = 10;
// CCIP Configuration per chain
struct CCIPConfig {
address router;
address linkToken;
uint64 chainSelector;
}
// WETH Configuration per chain
struct WETHConfig {
address weth9;
address weth10;
}
// Deployment addresses (will be populated during deployment)
struct DeploymentAddresses {
address weth9;
address weth10;
address ccipWETH9Bridge;
address ccipWETH10Bridge;
address ccipLogger;
}
DeploymentAddresses public deployed;
function run() external {
uint256 chainId = block.chainid;
// Get deployer address - when using --private-key flag, use msg.sender
// Otherwise get from env (PRIVATE_KEY should have 0x prefix in .env)
address deployer;
try vm.envUint("PRIVATE_KEY") returns (uint256 pk) {
deployer = vm.addr(pk);
} catch {
// If env read fails, use msg.sender (when --private-key is used from CLI)
deployer = msg.sender;
}
console.log("==========================================");
console.log("Multichain Deployment Script");
console.log("==========================================");
console.log("Chain ID:", chainId);
console.log("Deployer:", deployer);
console.log("Deployer Balance:", deployer.balance / 1e18, "ETH/Native");
// Get chain-specific configuration
CCIPConfig memory ccipConfig = getCCIPConfig(chainId);
WETHConfig memory wethConfig = getWETHConfig(chainId);
console.log("\nCCIP Configuration:");
console.log(" Router:", ccipConfig.router);
console.log(" LINK Token:", ccipConfig.linkToken);
console.log(" Chain Selector:", ccipConfig.chainSelector);
console.log("\nWETH Configuration:");
console.log(" WETH9:", wethConfig.weth9);
console.log(" WETH10:", wethConfig.weth10);
// startBroadcast() will use --private-key from CLI if provided
// Otherwise it will try to use PRIVATE_KEY from env
vm.startBroadcast();
// Determine deployment strategy based on chain
if (chainId == MAINNET) {
// Ethereum Mainnet: Only deploy CCIPLogger
console.log("\n=== Ethereum Mainnet Deployment ===");
console.log("Skipping WETH9, WETH10, and Bridges (already deployed)");
console.log("Deploying CCIPLogger only...");
deployed.ccipLogger = deployCcipLogger(ccipConfig);
} else {
// All other chains: Deploy everything
console.log("\n=== Full Deployment for Chain", chainId, "===");
// Deploy WETH9 if needed
if (wethConfig.weth9 == address(0)) {
console.log("\nDeploying WETH9...");
deployed.weth9 = deployWETH9();
} else {
console.log("\nUsing existing WETH9 at:", wethConfig.weth9);
deployed.weth9 = wethConfig.weth9;
}
// Deploy WETH10 if needed
if (wethConfig.weth10 == address(0)) {
console.log("\nDeploying WETH10...");
deployed.weth10 = deployWETH10();
} else {
console.log("\nUsing existing WETH10 at:", wethConfig.weth10);
deployed.weth10 = wethConfig.weth10;
}
// Deploy CCIP Bridges
console.log("\nDeploying CCIPWETH9Bridge...");
deployed.ccipWETH9Bridge = deployCCIPWETH9Bridge(
ccipConfig.router,
deployed.weth9,
ccipConfig.linkToken
);
console.log("\nDeploying CCIPWETH10Bridge...");
deployed.ccipWETH10Bridge = deployCCIPWETH10Bridge(
ccipConfig.router,
deployed.weth10,
ccipConfig.linkToken
);
// Deploy CCIPLogger
console.log("\nDeploying CCIPLogger...");
deployed.ccipLogger = deployCcipLogger(ccipConfig);
}
vm.stopBroadcast();
// Print deployment summary
printDeploymentSummary(chainId);
}
/**
* @notice Get CCIP configuration for a specific chain
*/
function getCCIPConfig(uint256 chainId) internal view returns (CCIPConfig memory) {
if (chainId == MAINNET) {
return CCIPConfig({
router: vm.envAddress("CCIP_ETH_ROUTER"),
linkToken: vm.envAddress("CCIP_ETH_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("ETH_MAINNET_SELECTOR"))
});
} else if (chainId == CRONOS) {
return CCIPConfig({
router: vm.envAddress("CCIP_CRONOS_ROUTER"),
linkToken: vm.envAddress("CCIP_CRONOS_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("CRONOS_SELECTOR"))
});
} else if (chainId == BSC) {
return CCIPConfig({
router: vm.envAddress("CCIP_BSC_ROUTER"),
linkToken: vm.envAddress("CCIP_BSC_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("BSC_SELECTOR"))
});
} else if (chainId == POLYGON) {
return CCIPConfig({
router: vm.envAddress("CCIP_POLYGON_ROUTER"),
linkToken: vm.envAddress("CCIP_POLYGON_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("POLYGON_SELECTOR"))
});
} else if (chainId == GNOSIS) {
return CCIPConfig({
router: vm.envAddress("CCIP_GNOSIS_ROUTER"),
linkToken: vm.envAddress("CCIP_GNOSIS_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("GNOSIS_SELECTOR"))
});
} else if (chainId == AVALANCHE) {
return CCIPConfig({
router: vm.envAddress("CCIP_AVALANCHE_ROUTER"),
linkToken: vm.envAddress("CCIP_AVALANCHE_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("AVALANCHE_SELECTOR"))
});
} else if (chainId == BASE) {
return CCIPConfig({
router: vm.envAddress("CCIP_BASE_ROUTER"),
linkToken: vm.envAddress("CCIP_BASE_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("BASE_SELECTOR"))
});
} else if (chainId == ARBITRUM) {
return CCIPConfig({
router: vm.envAddress("CCIP_ARBITRUM_ROUTER"),
linkToken: vm.envAddress("CCIP_ARBITRUM_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("ARBITRUM_SELECTOR"))
});
} else if (chainId == OPTIMISM) {
return CCIPConfig({
router: vm.envAddress("CCIP_OPTIMISM_ROUTER"),
linkToken: vm.envAddress("CCIP_OPTIMISM_LINK_TOKEN"),
chainSelector: uint64(vm.envUint("OPTIMISM_SELECTOR"))
});
} else {
revert("Unsupported chain");
}
}
/**
* @notice Get WETH configuration for a specific chain
*/
function getWETHConfig(uint256 chainId) internal returns (WETHConfig memory) {
if (chainId == MAINNET) {
return WETHConfig({
weth9: vm.envAddress("WETH9_MAINNET"),
weth10: vm.envAddress("WETH10_MAINNET")
});
} else if (chainId == CRONOS) {
address weth9 = vm.envOr("WETH9_CRONOS", address(0));
address weth10 = vm.envOr("WETH10_CRONOS", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == BSC) {
address weth9 = vm.envOr("WETH9_BSC", address(0));
address weth10 = vm.envOr("WETH10_BSC", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == POLYGON) {
address weth9 = vm.envOr("WETH9_POLYGON", address(0));
address weth10 = vm.envOr("WETH10_POLYGON", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == GNOSIS) {
address weth9 = vm.envOr("WETH9_GNOSIS", address(0));
address weth10 = vm.envOr("WETH10_GNOSIS", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == AVALANCHE) {
address weth9 = vm.envOr("WETH9_AVALANCHE", address(0));
address weth10 = vm.envOr("WETH10_AVALANCHE", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == BASE) {
address weth9 = vm.envOr("WETH9_BASE", address(0));
address weth10 = vm.envOr("WETH10_BASE", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == ARBITRUM) {
address weth9 = vm.envOr("WETH9_ARBITRUM", address(0));
address weth10 = vm.envOr("WETH10_ARBITRUM", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else if (chainId == OPTIMISM) {
address weth9 = vm.envOr("WETH9_OPTIMISM", address(0));
address weth10 = vm.envOr("WETH10_OPTIMISM", address(0));
return WETHConfig({weth9: weth9, weth10: weth10});
} else {
revert("Unsupported chain");
}
}
/**
* @notice Deploy WETH9 contract
*/
function deployWETH9() internal returns (address) {
WETH weth9 = new WETH();
return address(weth9);
}
/**
* @notice Deploy WETH10 contract
*/
function deployWETH10() internal returns (address) {
WETH10 weth10 = new WETH10();
return address(weth10);
}
/**
* @notice Deploy CCIPWETH9Bridge
*/
function deployCCIPWETH9Bridge(
address router,
address weth9,
address feeToken
) internal returns (address) {
CCIPWETH9Bridge bridge = new CCIPWETH9Bridge(router, weth9, feeToken);
return address(bridge);
}
/**
* @notice Deploy CCIPWETH10Bridge
*/
function deployCCIPWETH10Bridge(
address router,
address weth10,
address feeToken
) internal returns (address) {
CCIPWETH10Bridge bridge = new CCIPWETH10Bridge(router, weth10, feeToken);
return address(bridge);
}
/**
* @notice Deploy CCIPLogger
* @dev Note: This assumes CCIPLogger contract exists. If it uses Hardhat/OpenZeppelin,
* you may need to deploy it separately using the Hardhat script.
*/
function deployCcipLogger(CCIPConfig memory config) internal returns (address) {
// TODO: If CCIPLogger is a Solidity contract in this repo, deploy it here
// For now, this is a placeholder. CCIPLogger may need to be deployed via Hardhat
// due to OpenZeppelin dependencies.
// Example deployment (adjust based on actual CCIPLogger contract):
// CCIPLogger logger = new CCIPLogger(
// config.router,
// vm.envOr("AUTHORIZED_SIGNER", address(0)),
// config.chainSelector
// );
// return address(logger);
console.log("WARNING: CCIPLogger deployment not implemented in Foundry script.");
console.log("Please deploy CCIPLogger using the Hardhat script:");
console.log(" npm run deploy:logger:mainnet (for mainnet)");
console.log(" Or create a chain-specific deployment script.");
return address(0); // Placeholder
}
/**
* @notice Print deployment summary
*/
function printDeploymentSummary(uint256 chainId) internal view {
console.log("\n==========================================");
console.log("Deployment Summary - Chain ID:", chainId);
console.log("==========================================");
if (chainId != MAINNET) {
console.log("WETH9:", deployed.weth9);
console.log("WETH10:", deployed.weth10);
console.log("CCIPWETH9Bridge:", deployed.ccipWETH9Bridge);
console.log("CCIPWETH10Bridge:", deployed.ccipWETH10Bridge);
}
console.log("CCIPLogger:", deployed.ccipLogger);
console.log("\n==========================================");
console.log("Next Steps:");
console.log("1. Verify contracts on explorer");
console.log("2. Update .env with deployed addresses");
console.log("3. Configure bridge destinations");
console.log("4. Test cross-chain transfers");
console.log("==========================================");
}
}