Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
233 lines
8.1 KiB
Bash
Executable File
233 lines
8.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deploy Contracts with Retry Logic and Status Checking
|
|
# Includes transaction status verification and exponential backoff retry
|
|
|
|
set -euo pipefail
|
|
|
|
# Load IP configuration
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
|
log_section() { echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; echo -e "${CYAN}$1${NC}"; echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"; }
|
|
|
|
# Load environment
|
|
if [ -f "$PROJECT_ROOT/smom-dbis-138/.env" ]; then
|
|
set +e
|
|
source "$PROJECT_ROOT/smom-dbis-138/.env" 2>/dev/null || true
|
|
set -e
|
|
fi
|
|
|
|
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
|
RPC_URL="${RPC_URL_138:-http://${RPC_CORE_1}:8545}"
|
|
GAS_PRICE="${GAS_PRICE:-5000000000}" # 5 gwei default (higher for replacements)
|
|
|
|
if [ -z "$PRIVATE_KEY" ]; then
|
|
log_error "PRIVATE_KEY not set"
|
|
exit 1
|
|
fi
|
|
|
|
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || echo "")
|
|
if [ -z "$DEPLOYER" ]; then
|
|
log_error "Failed to derive deployer address"
|
|
exit 1
|
|
fi
|
|
|
|
# Retry configuration
|
|
MAX_RETRIES=3
|
|
INITIAL_RETRY_DELAY=5
|
|
MAX_RETRY_DELAY=30
|
|
|
|
log_section "Deploy with Retry and Status Check"
|
|
|
|
# Check transaction status before deployment
|
|
check_transaction_status() {
|
|
local deployer=$1
|
|
local rpc_url=$2
|
|
|
|
log_info "Checking transaction status for $deployer..."
|
|
|
|
LATEST_HEX=$(timeout 10 cast rpc eth_getTransactionCount "$deployer" latest --rpc-url "$rpc_url" 2>/dev/null || echo "")
|
|
PENDING_HEX=$(timeout 10 cast rpc eth_getTransactionCount "$deployer" pending --rpc-url "$rpc_url" 2>/dev/null || echo "")
|
|
|
|
if [ -z "$LATEST_HEX" ] || [ -z "$PENDING_HEX" ]; then
|
|
log_warn "Could not check transaction status"
|
|
return 1
|
|
fi
|
|
|
|
LATEST_CLEAN=$(echo "$LATEST_HEX" | tr -d '"')
|
|
PENDING_CLEAN=$(echo "$PENDING_HEX" | tr -d '"')
|
|
LATEST_DEC=$(python3 -c "print(int('$LATEST_CLEAN', 16))" 2>/dev/null || echo "0")
|
|
PENDING_DEC=$(python3 -c "print(int('$PENDING_CLEAN', 16))" 2>/dev/null || echo "0")
|
|
|
|
log_info "Latest nonce: $LATEST_DEC"
|
|
log_info "Pending nonce: $PENDING_DEC"
|
|
|
|
if [ "$PENDING_DEC" -gt "$LATEST_DEC" ]; then
|
|
local pending_count=$((PENDING_DEC - LATEST_DEC))
|
|
log_warn "⚠️ $pending_count pending transaction(s) detected"
|
|
log_info "Will use nonce $PENDING_DEC (next available)"
|
|
echo "$PENDING_DEC"
|
|
return 0
|
|
else
|
|
log_info "No pending transactions"
|
|
echo "$LATEST_DEC"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# Deploy with retry
|
|
deploy_with_retry() {
|
|
local contract_name=$1
|
|
local bytecode=$2
|
|
local nonce=$3
|
|
local gas_price=$4
|
|
local rpc_url=$5
|
|
local private_key=$6
|
|
|
|
local retry_count=0
|
|
local retry_delay=$INITIAL_RETRY_DELAY
|
|
|
|
while [ $retry_count -lt $MAX_RETRIES ]; do
|
|
log_info "Deploying $contract_name (attempt $((retry_count + 1))/$MAX_RETRIES)..."
|
|
log_info "Nonce: $nonce, Gas Price: $gas_price wei"
|
|
|
|
DEPLOY_OUTPUT=$(timeout 60 cast send \
|
|
--rpc-url "$rpc_url" \
|
|
--private-key "$private_key" \
|
|
--nonce "$nonce" \
|
|
--gas-price "$gas_price" \
|
|
--create "$bytecode" \
|
|
2>&1 || echo "")
|
|
|
|
if echo "$DEPLOY_OUTPUT" | grep -q "contractAddress\|transactionHash"; then
|
|
log_success "$contract_name deployment transaction sent!"
|
|
echo "$DEPLOY_OUTPUT"
|
|
return 0
|
|
elif echo "$DEPLOY_OUTPUT" | grep -q "Known transaction"; then
|
|
log_warn "Known transaction error - transaction already exists"
|
|
if [ $retry_count -lt $((MAX_RETRIES - 1)) ]; then
|
|
log_info "Increasing gas price for replacement..."
|
|
gas_price=$((gas_price * 11 / 10)) # Increase by 10%
|
|
log_info "New gas price: $gas_price wei"
|
|
fi
|
|
elif echo "$DEPLOY_OUTPUT" | grep -q "timeout\|Connection timed out"; then
|
|
log_warn "Connection timeout - will retry"
|
|
elif echo "$DEPLOY_OUTPUT" | grep -q "Replacement transaction underpriced"; then
|
|
log_warn "Replacement transaction underpriced - increasing gas price..."
|
|
gas_price=$((gas_price * 12 / 10)) # Increase by 20%
|
|
log_info "New gas price: $gas_price wei"
|
|
else
|
|
log_warn "Deployment failed: $(echo "$DEPLOY_OUTPUT" | tail -3)"
|
|
fi
|
|
|
|
retry_count=$((retry_count + 1))
|
|
if [ $retry_count -lt $MAX_RETRIES ]; then
|
|
log_info "Waiting $retry_delay seconds before retry..."
|
|
sleep $retry_delay
|
|
retry_delay=$((retry_delay * 2))
|
|
if [ $retry_delay -gt $MAX_RETRY_DELAY ]; then
|
|
retry_delay=$MAX_RETRY_DELAY
|
|
fi
|
|
fi
|
|
done
|
|
|
|
log_error "Failed to deploy $contract_name after $MAX_RETRIES attempts"
|
|
return 1
|
|
}
|
|
|
|
# Main deployment function
|
|
deploy_contract() {
|
|
local contract_name=$1
|
|
local contract_file=$2
|
|
local constructor_args=$3
|
|
|
|
log_section "Deploy $contract_name"
|
|
|
|
# Check status and get nonce
|
|
CURRENT_NONCE=$(check_transaction_status "$DEPLOYER" "$RPC_URL")
|
|
if [ -z "$CURRENT_NONCE" ]; then
|
|
log_error "Failed to get transaction status"
|
|
return 1
|
|
fi
|
|
|
|
# Ensure compiled
|
|
cd "$PROJECT_ROOT/smom-dbis-138"
|
|
if [ ! -f "out/$contract_file/$contract_name.json" ]; then
|
|
log_info "Compiling $contract_name..."
|
|
forge build --force "contracts/$contract_file/$contract_name.sol" 2>&1 | tail -5
|
|
fi
|
|
|
|
# Extract bytecode
|
|
BYTECODE=$(jq -r '.bytecode.object' "out/$contract_file/$contract_name.json" 2>/dev/null || echo "")
|
|
if [ -z "$BYTECODE" ] || [ "$BYTECODE" = "null" ]; then
|
|
log_error "Failed to extract bytecode"
|
|
return 1
|
|
fi
|
|
|
|
# Encode constructor arguments if provided
|
|
if [ -n "$constructor_args" ]; then
|
|
CONSTRUCTOR_ENCODED=$(eval "cast abi-encode $constructor_args" 2>/dev/null || echo "")
|
|
CONSTRUCTOR_ENCODED="${CONSTRUCTOR_ENCODED#0x}"
|
|
BYTECODE_CLEAN="${BYTECODE#0x}"
|
|
FULL_BYTECODE="0x${BYTECODE_CLEAN}${CONSTRUCTOR_ENCODED}"
|
|
else
|
|
FULL_BYTECODE="$BYTECODE"
|
|
fi
|
|
|
|
# Deploy with retry
|
|
DEPLOY_OUTPUT=$(deploy_with_retry "$contract_name" "$FULL_BYTECODE" "$CURRENT_NONCE" "$GAS_PRICE" "$RPC_URL" "$PRIVATE_KEY")
|
|
|
|
if [ $? -eq 0 ]; then
|
|
# Extract contract address
|
|
CONTRACT_ADDR=$(echo "$DEPLOY_OUTPUT" | grep -oE "contractAddress.*0x[a-fA-F0-9]{40}|0x[a-fA-F0-9]{40}" | grep -oE "0x[a-fA-F0-9]{40}" | head -1 || echo "")
|
|
if [ -n "$CONTRACT_ADDR" ]; then
|
|
log_success "$contract_name deployed to: $CONTRACT_ADDR"
|
|
echo "$CONTRACT_ADDR"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# Deploy WETH9 Bridge
|
|
WETH9_BRIDGE=$(deploy_contract "CCIPWETH9Bridge" "bridge/ccip/CCIPWETH9Bridge.sol" \
|
|
"constructor(address,address,address) $CCIP_ROUTER 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 $CCIP_FEE_TOKEN" || echo "")
|
|
|
|
# Deploy WETH10 Bridge
|
|
WETH10_BRIDGE=$(deploy_contract "CCIPWETH10Bridge" "bridge/ccip/CCIPWETH10Bridge.sol" \
|
|
"constructor(address,address,address) $CCIP_ROUTER 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f $CCIP_FEE_TOKEN" || echo "")
|
|
|
|
# Summary
|
|
log_section "Deployment Summary"
|
|
|
|
if [ -n "$WETH9_BRIDGE" ]; then
|
|
log_success "WETH9 Bridge: $WETH9_BRIDGE"
|
|
else
|
|
log_error "WETH9 Bridge: Deployment failed"
|
|
fi
|
|
|
|
if [ -n "$WETH10_BRIDGE" ]; then
|
|
log_success "WETH10 Bridge: $WETH10_BRIDGE"
|
|
else
|
|
log_error "WETH10 Bridge: Deployment failed"
|
|
fi
|