- Resolve stash: merge load_deployment_env path with secure-secrets and CR/LF RPC strip - create-pmm-full-mesh-chain138.sh delegates to sync-chain138-pmm-pools-from-json.sh - env.additions.example: canonical PMM pool defaults (cUSDT/USDT per crosscheck) - Include Chain138 scripts, official mirror deploy scaffolding, and prior staged changes Made-with: Cursor
245 lines
7.0 KiB
Bash
Executable File
245 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# End-to-end dry-run for Ethereum Mainnet deployment
|
|
# Validates compilation, parameters, and deployment order without actually deploying
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
|
|
log_info "=== Ethereum Mainnet Deployment Dry-Run ==="
|
|
|
|
# Load environment variables
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
source "$PROJECT_ROOT/.env"
|
|
else
|
|
log_error "Error: .env file not found"
|
|
exit 1
|
|
fi
|
|
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
|
|
# Disable exit on error for arithmetic operations
|
|
set +e
|
|
|
|
# Function to check if command exists
|
|
check_command() {
|
|
if ! command -v "$1" &> /dev/null; then
|
|
log_error "❌ $1 not found"
|
|
((ERRORS++))
|
|
return 1
|
|
else
|
|
log_success "✅ $1 found"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# Function to validate address
|
|
validate_address() {
|
|
local addr=$1
|
|
local name=$2
|
|
if [[ ! "$addr" =~ ^0x[0-9a-fA-F]{40}$ ]]; then
|
|
log_error "❌ Invalid $name address: $addr"
|
|
((ERRORS++))
|
|
return 1
|
|
else
|
|
log_success "✅ $name address valid: $addr"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# Step 1: Check required tools
|
|
log_info "Step 1: Checking required tools..."
|
|
check_command "forge"
|
|
check_command "cast"
|
|
check_command "node"
|
|
check_command "npm"
|
|
|
|
# Step 2: Validate environment variables
|
|
log_info "Step 2: Validating environment variables..."
|
|
|
|
# Required variables
|
|
REQUIRED_VARS=("PRIVATE_KEY" "ETHEREUM_MAINNET_RPC")
|
|
for var in "${REQUIRED_VARS[@]}"; do
|
|
if [ -z "${!var}" ]; then
|
|
log_error "❌ Missing required variable: $var"
|
|
((ERRORS++))
|
|
else
|
|
log_success "✅ $var is set"
|
|
fi
|
|
done
|
|
|
|
# Optional but recommended
|
|
if [ -z "$CCIP_ETH_ROUTER" ]; then
|
|
CCIP_ETH_ROUTER="0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D"
|
|
log_warn "⚠️ CCIP_ETH_ROUTER not set, using default: $CCIP_ETH_ROUTER"
|
|
((WARNINGS++))
|
|
else
|
|
validate_address "$CCIP_ETH_ROUTER" "CCIP_ETH_ROUTER"
|
|
fi
|
|
|
|
if [ -z "$CCIP_FEE_TOKEN" ]; then
|
|
CCIP_FEE_TOKEN="0x514910771AF9Ca656af840dff83E8264EcF986CA" # LINK token
|
|
log_warn "⚠️ CCIP_FEE_TOKEN not set, using default: $CCIP_FEE_TOKEN"
|
|
((WARNINGS++))
|
|
else
|
|
validate_address "$CCIP_FEE_TOKEN" "CCIP_FEE_TOKEN"
|
|
fi
|
|
|
|
# Validate private key format
|
|
if [[ ! "$PRIVATE_KEY" =~ ^0x[0-9a-fA-F]{64}$ ]] && [[ ! "$PRIVATE_KEY" =~ ^[0-9a-fA-F]{64}$ ]]; then
|
|
log_error "❌ Invalid PRIVATE_KEY format"
|
|
((ERRORS++))
|
|
else
|
|
log_success "✅ PRIVATE_KEY format valid"
|
|
fi
|
|
|
|
|
|
# Step 3: Validate contract addresses
|
|
log_info "Step 3: Validating contract addresses..."
|
|
WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
|
WETH10_ADDRESS="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F"
|
|
validate_address "$WETH9_ADDRESS" "WETH9"
|
|
validate_address "$WETH10_ADDRESS" "WETH10"
|
|
|
|
# Step 4: Compile contracts
|
|
log_info "Step 4: Compiling contracts..."
|
|
cd "$PROJECT_ROOT"
|
|
# Load .env via dotenv (RPC CR/LF trim). Fallback: raw source.
|
|
if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
|
load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}"
|
|
elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$PROJECT_ROOT/.env"
|
|
set +a
|
|
elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$REPO_ROOT/.env"
|
|
set +a
|
|
fi
|
|
|
|
echo "Compiling CCIPWETH9Bridge..."
|
|
if forge build --contracts contracts/ccip/CCIPWETH9Bridge.sol 2>&1 | grep -q "Compiler run successful\|No files changed"; then
|
|
log_success "✅ CCIPWETH9Bridge compiled"
|
|
else
|
|
log_error "❌ CCIPWETH9Bridge compilation failed"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
echo "Compiling CCIPWETH10Bridge..."
|
|
if forge build --contracts contracts/ccip/CCIPWETH10Bridge.sol 2>&1 | grep -q "Compiler run successful\|No files changed"; then
|
|
log_success "✅ CCIPWETH10Bridge compiled"
|
|
else
|
|
log_error "❌ CCIPWETH10Bridge compilation failed"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
echo "Checking CCIPLogger..."
|
|
if [ -d "node_modules/@chainlink/contracts-ccip" ]; then
|
|
log_success "✅ Chainlink contracts installed"
|
|
if [ -f "contracts/ccip-integration/CCIPLogger.sol" ]; then
|
|
log_success "✅ CCIPLogger contract exists"
|
|
else
|
|
log_error "❌ CCIPLogger contract not found"
|
|
((ERRORS++))
|
|
fi
|
|
else
|
|
log_warn "⚠️ @chainlink/contracts-ccip not installed, skipping CCIPLogger check"
|
|
log_warn " Run: npm install"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
|
|
# Step 5: Validate deployment scripts
|
|
log_info "Step 5: Validating deployment scripts..."
|
|
|
|
echo "Checking DeployCCIPWETH9Bridge.s.sol..."
|
|
if [ -f "script/DeployCCIPWETH9Bridge.s.sol" ]; then
|
|
log_success "✅ DeployCCIPWETH9Bridge.s.sol exists"
|
|
else
|
|
log_error "❌ DeployCCIPWETH9Bridge.s.sol not found"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
echo "Checking DeployCCIPWETH10Bridge.s.sol..."
|
|
if [ -f "script/DeployCCIPWETH10Bridge.s.sol" ]; then
|
|
log_success "✅ DeployCCIPWETH10Bridge.s.sol exists"
|
|
else
|
|
log_error "❌ DeployCCIPWETH10Bridge.s.sol not found"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
echo "Checking deploy-ccip-logger.js..."
|
|
if [ -f "scripts/ccip-deployment/deploy-ccip-logger.js" ]; then
|
|
log_success "✅ deploy-ccip-logger.js exists"
|
|
else
|
|
log_error "❌ deploy-ccip-logger.js not found"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
|
|
# Step 6: Test RPC connection
|
|
log_info "Step 6: Testing RPC connection..."
|
|
if [ -n "$ETHEREUM_MAINNET_RPC" ]; then
|
|
CHAIN_ID=$(cast chain-id --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null || echo "")
|
|
if [ "$CHAIN_ID" == "1" ]; then
|
|
log_success "✅ RPC connected to Ethereum Mainnet (Chain ID: 1)"
|
|
elif [ -n "$CHAIN_ID" ]; then
|
|
log_error "❌ RPC connected to wrong chain (Chain ID: $CHAIN_ID, expected: 1)"
|
|
((ERRORS++))
|
|
else
|
|
log_warn "⚠️ Could not verify RPC connection"
|
|
((WARNINGS++))
|
|
fi
|
|
else
|
|
log_error "❌ ETHEREUM_MAINNET_RPC not set"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
|
|
# Step 7: Validate deployment order
|
|
log_info "Step 7: Validating deployment order..."
|
|
echo " 1. CCIPLogger (no dependencies on new contracts)"
|
|
echo " 2. CCIPWETH9Bridge (depends on CCIP Router)"
|
|
echo " 3. CCIPWETH10Bridge (depends on CCIP Router)"
|
|
log_success "✅ Deployment order is correct"
|
|
|
|
# Step 8: Estimate gas costs
|
|
log_info "Step 8: Estimating gas costs..."
|
|
if [ -f "$SCRIPT_DIR/calculate-conservative-costs.sh" ]; then
|
|
echo "Running gas cost estimation..."
|
|
"$SCRIPT_DIR/calculate-conservative-costs.sh" 2>&1 | tail -10
|
|
else
|
|
log_warn "⚠️ Gas cost estimation script not found"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
|
|
# Re-enable exit on error
|
|
set -e
|
|
|
|
# Summary
|
|
log_info "=== Dry-Run Summary ==="
|
|
if [ "$ERRORS" -eq 0 ]; then
|
|
log_success "✅ All checks passed!"
|
|
if [ "$WARNINGS" -gt 0 ]; then
|
|
log_warn "⚠️ $WARNINGS warning(s)"
|
|
fi
|
|
log_success "Ready for deployment!"
|
|
exit 0
|
|
else
|
|
log_error "❌ $ERRORS error(s) found"
|
|
if [ "$WARNINGS" -gt 0 ]; then
|
|
log_warn "⚠️ $WARNINGS warning(s)"
|
|
fi
|
|
log_error "Please fix errors before deploying"
|
|
exit 1
|
|
fi
|