Files
smom-dbis-138/docs/deployment/MULTICHAIN_DEPLOYMENT_RUNBOOK.md
defiQUG 1fb7266469 Add Oracle Aggregator and CCIP Integration
- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control.
- Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities.
- Created .gitmodules to include OpenZeppelin contracts as a submodule.
- Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment.
- Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks.
- Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring.
- Created scripts for resource import and usage validation across non-US regions.
- Added tests for CCIP error handling and integration to ensure robust functionality.
- Included various new files and directories for the orchestration portal and deployment scripts.
2025-12-12 14:57:48 -08:00

12 KiB

Multichain Deployment Runbook

Last Updated: 2025-01-27 Purpose: Comprehensive guide for deploying smart contracts to multiple chains using Foundry

Overview

This runbook covers deployment of the complete contract suite to:

  • Ethereum Mainnet (chainId 1): Only CCIPLogger (other contracts already deployed)
  • Cronos (chainId 25): All contracts
  • BSC (chainId 56): All contracts
  • Polygon PoS (chainId 137): All contracts
  • Gnosis Chain (chainId 100): All contracts

Prerequisites

1. Environment Setup

  1. Copy environment template:

    cp .env.example .env
    
  2. Fill in all required variables in .env:

    • PRIVATE_KEY: Your deployer private key
    • RPC URLs for all chains
    • Explorer API keys for verification
    • CCIP router addresses per chain
    • LINK token addresses per chain
  3. Verify Foundry installation:

    forge --version
    # Should be >= 0.2.0
    
  4. Install dependencies (if using Hardhat for CCIPLogger):

    npm install
    npm install @openzeppelin/contracts@5.0.2
    npm install @chainlink/contracts-ccip
    

2. Verify Configuration

Check that all environment variables are set:

# Check mainnet config
echo $ETH_MAINNET_RPC_URL
echo $CCIP_ETH_ROUTER
echo $CCIP_ETH_LINK_TOKEN

# Check other chains
echo $CRONOS_RPC_URL
echo $BSC_RPC_URL
echo $POLYGON_RPC_URL
echo $GNOSIS_RPC_URL

3. Get Real-Time Gas Prices

Before checking balances, fetch real-time gas prices:

# Fetch real-time gas prices for all chains
./scripts/deployment/get-multichain-gas-prices.sh

# Update documentation with real-time prices
./scripts/deployment/update-gas-estimates.sh

This will:

  • Fetch current gas prices from configured APIs
  • Calculate deployment costs for all chains
  • Update documentation with real-time estimates
  • Show you exactly how much you need

4. Verify Wallet Balance

Ensure your deployer wallet has sufficient native tokens for gas:

# Check balances (adjust RPC URLs as needed)
cast balance $DEPLOYER_ADDRESS --rpc-url $ETH_MAINNET_RPC_URL
cast balance $DEPLOYER_ADDRESS --rpc-url $CRONOS_RPC_URL
cast balance $DEPLOYER_ADDRESS --rpc-url $BSC_RPC_URL
cast balance $DEPLOYER_ADDRESS --rpc-url $POLYGON_RPC_URL
cast balance $DEPLOYER_ADDRESS --rpc-url $GNOSIS_RPC_URL

Recommended minimum balances (see Gas and Token Requirements for details):

  • Ethereum Mainnet: 0.20 ETH (for CCIPLogger deployment)
  • Cronos: 15 CRO (for all 5 contracts)
  • BSC: 0.06 BNB (for all 5 contracts)
  • Polygon: 1.0 MATIC (for all 5 contracts)
  • Gnosis: 0.05 xDAI (for all 5 contracts)

Total Estimated Cost: ~$520 USD (with buffers)


Deployment Commands

Ethereum Mainnet - CCIPLogger Only

Status: WETH9, WETH10, CCIPWETH9Bridge, CCIPWETH10Bridge are already deployed.

Deploy CCIPLogger:

# Option 1: Using Foundry (if CCIPLogger is compatible)
forge script script/DeployCCIPLoggerOnly.s.sol:DeployCCIPLoggerOnly \
  --rpc-url mainnet \
  --chain-id 1 \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  -vvvv

# Option 2: Using Hardhat (recommended for CCIPLogger)
npm install @openzeppelin/contracts@5.0.2
npx hardhat run scripts/ccip-deployment/deploy-ccip-logger.js --network mainnet

Verify CCIPLogger:

# If deployed via Foundry, verification is automatic with --verify flag
# If deployed via Hardhat:
npx hardhat verify --network mainnet \
  <CCIPLOGGER_ADDRESS> \
  "$CCIP_ETH_ROUTER" \
  "$AUTHORIZED_SIGNER" \
  "$CHAIN138_SELECTOR"

Cronos (Chain ID 25)

Deploy all contracts:

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url cronos \
  --chain-id 25 \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  -vvvv

Verify contracts (if automatic verification fails):

# WETH9
forge verify-contract \
  --chain-id 25 \
  --num-of-optimizations 200 \
  --watch \
  <WETH9_ADDRESS> \
  contracts/tokens/WETH.sol:WETH \
  $CRONOSCAN_API_KEY

# WETH10
forge verify-contract \
  --chain-id 25 \
  --num-of-optimizations 200 \
  --watch \
  <WETH10_ADDRESS> \
  contracts/tokens/WETH10.sol:WETH10 \
  $CRONOSCAN_API_KEY

# CCIPWETH9Bridge
forge verify-contract \
  --chain-id 25 \
  --num-of-optimizations 200 \
  --watch \
  <BRIDGE_ADDRESS> \
  contracts/ccip/CCIPWETH9Bridge.sol:CCIPWETH9Bridge \
  $CRONOSCAN_API_KEY \
  --constructor-args $(cast abi-encode "constructor(address,address,address)" $CCIP_CRONOS_ROUTER $WETH9_ADDRESS $CCIP_CRONOS_LINK_TOKEN)

# CCIPWETH10Bridge
forge verify-contract \
  --chain-id 25 \
  --num-of-optimizations 200 \
  --watch \
  <BRIDGE_ADDRESS> \
  contracts/ccip/CCIPWETH10Bridge.sol:CCIPWETH10Bridge \
  $CRONOSCAN_API_KEY \
  --constructor-args $(cast abi-encode "constructor(address,address,address)" $CCIP_CRONOS_ROUTER $WETH10_ADDRESS $CCIP_CRONOS_LINK_TOKEN)

BSC (Chain ID 56)

Deploy all contracts:

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url bsc \
  --chain-id 56 \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  -vvvv

Verify contracts (if automatic verification fails):

# Similar to Cronos, but use BSCSCAN_API_KEY
forge verify-contract \
  --chain-id 56 \
  --num-of-optimizations 200 \
  --watch \
  <CONTRACT_ADDRESS> \
  <CONTRACT_PATH>:<CONTRACT_NAME> \
  $BSCSCAN_API_KEY \
  --constructor-args <ENCODED_ARGS>

Polygon PoS (Chain ID 137)

Deploy all contracts:

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url polygon \
  --chain-id 137 \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  -vvvv

Verify contracts (if automatic verification fails):

# Use POLYGONSCAN_API_KEY
forge verify-contract \
  --chain-id 137 \
  --num-of-optimizations 200 \
  --watch \
  <CONTRACT_ADDRESS> \
  <CONTRACT_PATH>:<CONTRACT_NAME> \
  $POLYGONSCAN_API_KEY \
  --constructor-args <ENCODED_ARGS>

Note: Polygon CCIP Router is available at 0x3C3D92629A02a8D95D5CB9650fe49C3544f69B43


Gnosis Chain (Chain ID 100)

Deploy all contracts:

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url gnosis \
  --chain-id 100 \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  -vvvv

Verify contracts (if automatic verification fails):

# Use GNOSISSCAN_API_KEY
forge verify-contract \
  --chain-id 100 \
  --num-of-optimizations 200 \
  --watch \
  <CONTRACT_ADDRESS> \
  <CONTRACT_PATH>:<CONTRACT_NAME> \
  $GNOSISSCAN_API_KEY \
  --constructor-args <ENCODED_ARGS>

Post-Deployment Steps

1. Save Deployment Addresses

After each deployment, save the addresses to your .env file:

# Example for Cronos
echo "WETH9_CRONOS=<deployed_address>" >> .env
echo "WETH10_CRONOS=<deployed_address>" >> .env
echo "CCIPWETH9BRIDGE_CRONOS=<deployed_address>" >> .env
echo "CCIPWETH10BRIDGE_CRONOS=<deployed_address>" >> .env
echo "CCIPLOGGER_CRONOS=<deployed_address>" >> .env

2. Verify All Contracts

Verify all contracts on their respective explorers:

3. Configure Bridge Destinations

For each bridge contract, configure destination chains:

# Example: Configure WETH9 Bridge on Cronos to send to Mainnet
cast send <CCIPWETH9BRIDGE_CRONOS> \
  "addDestination(uint64,address)" \
  $ETH_MAINNET_SELECTOR \
  $CCIPWETH9BRIDGE_MAINNET \
  --rpc-url cronos \
  --private-key $PRIVATE_KEY

4. Test Cross-Chain Transfers

Test a small cross-chain transfer to verify everything works:

# Example: Send WETH9 from Cronos to Mainnet
cast send <WETH9_CRONOS> \
  "approve(address,uint256)" \
  <CCIPWETH9BRIDGE_CRONOS> \
  1000000000000000000 \
  --rpc-url cronos \
  --private-key $PRIVATE_KEY

cast send <CCIPWETH9BRIDGE_CRONOS> \
  "sendCrossChain(uint64,address,uint256)" \
  $ETH_MAINNET_SELECTOR \
  <RECIPIENT_ADDRESS> \
  1000000000000000000 \
  --rpc-url cronos \
  --private-key $PRIVATE_KEY

Gas and Token Requirements

📊 For detailed gas cost breakdowns and token requirements, see: Gas and Token Requirements

Quick Reference: Minimum Balances

Chain Token Minimum Recommended
Mainnet ETH 0.15 ETH 0.20 ETH
Cronos CRO 8.76 CRO 15 CRO
BSC BNB 0.044 BNB 0.06 BNB
Polygon MATIC 0.44 MATIC 1.0 MATIC
Gnosis xDAI 0.0175 xDAI 0.05 xDAI

Total Gas Requirements

  • Ethereum Mainnet: 3,000,000 gas (CCIPLogger only)
  • Other Chains: 8,760,000 gas (all 5 contracts: WETH9, WETH10, 2 Bridges, CCIPLogger)

Gas Price Strategies

Ethereum Mainnet

  • Strategy: Use EIP-1559 (automatic)
  • Max Fee: Check current gas prices
  • Priority Fee: 2-5 gwei

Cronos

  • Strategy: Fixed gas price
  • Gas Price: ~500 gwei (very low)
  • Note: Cronos uses CRO for gas

BSC

  • Strategy: Fixed gas price
  • Gas Price: ~3-5 gwei
  • Note: BSC uses BNB for gas

Polygon

  • Strategy: Fixed gas price
  • Gas Price: ~30-100 gwei
  • Note: Polygon uses MATIC for gas

Gnosis

  • Strategy: Fixed gas price
  • Gas Price: ~1 gwei
  • Note: Gnosis uses xDAI for gas

Network-Specific Caveats

Cronos

  • Finality: ~6 seconds
  • CCIP Support: Verify CCIP router availability
  • RPC: May have rate limits

BSC

  • Finality: ~3 seconds
  • CCIP Support: Verify CCIP router availability
  • Gas: Very cheap, but watch for congestion

Polygon

  • Finality: ~2 seconds
  • CCIP Support: Available
  • Router: 0x3C3D92629A02a8D95D5CB9650fe49C3544f69B43
  • LINK Token: 0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39

Gnosis

  • Finality: ~5 seconds
  • CCIP Support: Verify CCIP router availability
  • Gas: Very cheap

Troubleshooting

RPC Connection Issues

# Test RPC connectivity
cast block-number --rpc-url $ETH_MAINNET_RPC_URL
cast block-number --rpc-url $CRONOS_RPC_URL
cast block-number --rpc-url $BSC_RPC_URL
cast block-number --rpc-url $POLYGON_RPC_URL
cast block-number --rpc-url $GNOSIS_RPC_URL

Contract Verification Fails

  1. Check compiler settings match:

    # Verify optimizer settings
    grep optimizer foundry.toml
    grep optimizer_runs foundry.toml
    
  2. Verify constructor arguments:

    # Encode constructor args manually
    cast abi-encode "constructor(address,address,address)" \
      $ROUTER $WETH $LINK
    
  3. Use explicit verification:

    forge verify-contract \
      --chain-id <CHAIN_ID> \
      --num-of-optimizations 200 \
      --watch \
      <ADDRESS> \
      <CONTRACT_PATH>:<CONTRACT_NAME> \
      <API_KEY> \
      --constructor-args <ENCODED_ARGS>
    

CCIPLogger Deployment Issues

If CCIPLogger fails to deploy via Foundry:

  1. Use Hardhat script instead: npm run deploy:logger:mainnet
  2. Ensure OpenZeppelin v5.0.2+ is installed
  3. Check that CCIP contracts are available

Deployment Checklist

Pre-Deployment

  • Environment variables configured
  • Wallet balances sufficient
  • RPC endpoints tested
  • Contracts compile successfully
  • Tests pass

Deployment

  • Ethereum Mainnet: CCIPLogger deployed
  • Cronos: All contracts deployed
  • BSC: All contracts deployed
  • Polygon: All contracts deployed
  • Gnosis: All contracts deployed

Post-Deployment

  • All contracts verified on explorers
  • Deployment addresses saved to .env
  • Bridge destinations configured
  • Cross-chain transfers tested
  • Monitoring set up

Support

For issues or questions:

  • Check deployment logs
  • Review contract documentation
  • Verify configuration
  • Check troubleshooting section above

References