#!/usr/bin/env bash # Unified Contract Deployment Script # Supports both parallel and ordered deployment modes set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/init.sh" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" 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 # Default values MODE="${MODE:-ordered}" # ordered or parallel RPC_URL="${RPC_URL:-http://localhost:8545}" PRIVATE_KEY="${PRIVATE_KEY:-}" DRY_RUN="${DRY_RUN:-false}" usage() { cat < /dev/null 2>&1; then log_error "Error: RPC endpoint is not accessible at $RPC_URL" exit 1 fi log_success "✅ RPC endpoint is accessible" # Export variables export PRIVATE_KEY export RPC_URL export CCIP_ROUTER="${CCIP_ROUTER:-}" export CCIP_FEE_TOKEN="${CCIP_FEE_TOKEN:-0x0000000000000000000000000000000000000000}" export ORACLE_DESCRIPTION="${ORACLE_DESCRIPTION:-ETH/USD Price Feed}" export ORACLE_HEARTBEAT="${ORACLE_HEARTBEAT:-60}" export ORACLE_DEVIATION_THRESHOLD="${ORACLE_DEVIATION_THRESHOLD:-50}" # Function to update .env file update_env() { local key=$1 local value=$2 if [ "$DRY_RUN" = "true" ]; then echo " [DRY RUN] Would set ${key}=${value}" return fi if grep -q "^${key}=" .env 2>/dev/null; then sed -i "s|^${key}=.*|${key}=${value}|" .env else echo "${key}=${value}" >> .env fi } # Function to deploy a contract deploy_contract() { local name=$1 local script=$2 local sig="${3:-run()}" log_section "Deploying $name" if [ "$DRY_RUN" = "true" ]; then echo " [DRY RUN] Would deploy: $script" return fi forge script "$script" \ --rpc-url "$RPC_URL" \ --broadcast \ --private-key "$PRIVATE_KEY" \ --sig "$sig" \ -vvv 2>&1 | tee "/tmp/deploy-${name}.log" # Extract address from log (simplified - may need adjustment) local address=$(grep -oP "Deployed to: \K0x[a-fA-F0-9]{40}" "/tmp/deploy-${name}.log" | tail -1 || echo "") if [ -n "$address" ]; then update_env "${name^^}_ADDRESS" "$address" log_success "✅ $name deployed at: $address" fi } echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "🚀 Unified Contract Deployment" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Mode: $MODE" echo "RPC URL: $RPC_URL" echo "Dry Run: $DRY_RUN" echo "" if [ "$MODE" = "parallel" ]; then log_info "Deploying contracts in parallel mode..." # Deploy independent contracts in parallel deploy_contract "Multicall" "script/DeployMulticall.s.sol" & deploy_contract "CREATE2Factory" "script/DeployCREATE2Factory.s.sol" & deploy_contract "Oracle" "script/DeployOracle.s.sol" & wait log_success "✅ Parallel deployment complete" else log_info "Deploying contracts in ordered mode (respecting dependencies)..." # Phase 1: Core utilities (no dependencies) deploy_contract "Multicall" "script/DeployMulticall.s.sol" deploy_contract "CREATE2Factory" "script/DeployCREATE2Factory.s.sol" # Phase 2: Oracle (no dependencies) deploy_contract "Oracle" "script/DeployOracle.s.sol" # Phase 3: Governance (may depend on oracle) if [ -f "script/DeployMultiSig.s.sol" ]; then deploy_contract "MultiSig" "script/DeployMultiSig.s.sol" fi log_success "✅ Ordered deployment complete" fi echo "" log_success "🎉 All contracts deployed successfully!"