#!/usr/bin/env bash # Deployer gas auto-route orchestrator: for each chain where deployer native balance is below # threshold, dispatch to internal (138), Protocolink (public), or manual (Wemix) path. # Uses config/deployer-gas-routes.json and smom-dbis-138/.env for RPC and deployer. # # Usage: # ./scripts/deployment/deployer-gas-auto-route.sh [--dry-run] [--chain CHAIN_ID] [--no-execute] # # From repo root; load-project-env sources smom-dbis-138/.env # # Requires: jq, curl, cast (Foundry). Optional: Node for protocolink-swap-to-gas.js. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" if [[ -f "$PROJECT_ROOT/scripts/lib/load-project-env.sh" ]]; then source "$PROJECT_ROOT/scripts/lib/load-project-env.sh" fi CONFIG="${PROJECT_ROOT}/config/deployer-gas-routes.json" DRY_RUN=false NO_EXECUTE=false CHAIN_FILTER="" for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; --no-execute) NO_EXECUTE=true ;; --chain=*) CHAIN_FILTER="${arg#*=}" ;; --chain) CHAIN_FILTER="${2:-}"; shift ;; esac done if [[ ! -f "$CONFIG" ]]; then echo "ERROR: Config not found: $CONFIG" >&2 exit 1 fi DEPLOYER="${DEPLOYER_ADDRESS:-$(jq -r '.deployerAddress // empty' "$CONFIG")}" if [[ -z "$DEPLOYER" && -n "${PRIVATE_KEY:-}" ]] && command -v cast &>/dev/null; then DEPLOYER="$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)" fi DEPLOYER="${DEPLOYER:-0x4A666F96fC8764181194447A7dFdb7d471b301C8}" # Map chainId to RPC env var name (from check-balances-gas-and-deploy.sh) get_rpc_for_chain() { local c="$1" case "$c" in 1) echo "${ETHEREUM_MAINNET_RPC:-}" ;; 56) echo "${BSC_RPC_URL:-${BSC_MAINNET_RPC:-}}" ;; 137) echo "${POLYGON_MAINNET_RPC:-}" ;; 138) echo "${RPC_URL_138:-}" ;; 10) echo "${OPTIMISM_MAINNET_RPC:-}" ;; 42161) echo "${ARBITRUM_MAINNET_RPC:-}" ;; 8453) echo "${BASE_MAINNET_RPC:-}" ;; 43114) echo "${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-}}" ;; 100) echo "${GNOSIS_MAINNET_RPC:-${GNOSIS_RPC:-}}" ;; 25) echo "${CRONOS_RPC_URL:-}" ;; 42220) echo "${CELO_RPC_URL:-}" ;; 1111) echo "${WEMIX_RPC_URL:-}" ;; 651940) echo "${ALLTRA_MAINNET_RPC:-}" ;; *) echo "" ;; esac } # thresholdEther is human number; convert to wei for ETH-like 18 decimals. For MATIC/BNB/etc same scale. threshold_to_wei() { local th="$1" echo "${th}" | awk 'BEGIN { OFMT="%.0f" } { gsub(/,/,""); printf "%.0f", $0 * 1e18 }' } echo "==============================================" echo "Deployer gas auto-route" echo "Deployer: ${DEPLOYER:0:6}...${DEPLOYER: -6}" echo "Config: $CONFIG" echo "==============================================" echo "" needs_gas=() while read -r line; do chain_id="$(echo "$line" | jq -r '.chainId')" name="$(echo "$line" | jq -r '.name')" method="$(echo "$line" | jq -r '.method')" th_ether="$(echo "$line" | jq -r '.thresholdEther')" native_sym="$(echo "$line" | jq -r '.nativeSymbol // "native"')" [[ "$chain_id" == "null" || -z "$chain_id" ]] && continue [[ -n "$CHAIN_FILTER" && "$CHAIN_FILTER" != "$chain_id" ]] && continue rpc="$(get_rpc_for_chain "$chain_id")" if [[ -z "$rpc" ]]; then echo "[$chain_id] $name — no RPC configured; skip" continue fi balance_wei="$(cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0")" [[ -z "$balance_wei" || ! "$balance_wei" =~ ^[0-9]+$ ]] && balance_wei="0" th_wei="$(threshold_to_wei "$th_ether")" if [[ "$(echo "$balance_wei >= $th_wei" | bc 2>/dev/null)" -eq 1 ]]; then echo "[$chain_id] $name — balance OK (>= $th_ether $native_sym); skip" continue fi echo "[$chain_id] $name — below threshold ($th_ether); method=$method" needs_gas+=("$chain_id|$name|$method|$line") done < <(jq -c '.chains[]' "$CONFIG" 2>/dev/null) echo "" if [[ ${#needs_gas[@]} -eq 0 ]]; then echo "No chains need gas. Done." exit 0 fi echo "Chains needing gas: ${#needs_gas[@]}" echo "" for entry in "${needs_gas[@]}"; do IFS='|' read -r chain_id name method line <<< "$entry" echo "--- $name (chain $chain_id) ---" case "$method" in internal) if [[ "$chain_id" == "138" ]]; then "$SCRIPT_DIR/chain138-tokens-to-gas.sh" ${DRY_RUN:+--dry-run} 2>&1 || true else echo " Internal path only for chain 138; skip." fi ;; protocolink) if command -v node &>/dev/null; then node "$SCRIPT_DIR/protocolink-swap-to-gas.cjs" --chain-id "$chain_id" --no-execute 2>&1 || true else echo " Install Node to run protocolink-swap-to-gas.cjs for this chain." fi ;; manual) manual_links="$(echo "$line" | jq -r '.manualLinks[]? // empty' 2>/dev/null)" manual_instr="$(echo "$line" | jq -r '.manualInstructions // empty' 2>/dev/null)" echo " $manual_instr" if [[ -n "$manual_links" ]]; then echo "$manual_links" | while read -r url; do [[ -n "$url" ]] && echo " $url"; done fi if [[ "$chain_id" == "25" || "$chain_id" == "1111" ]]; then echo " For all swap routes (multiple aggregators): ./scripts/deployment/acquire-cro-and-wemix-gas.sh" fi if [[ "$chain_id" == "1111" ]] && command -v node &>/dev/null; then node "$SCRIPT_DIR/wemix-acquire-via-lifi.js" --dry-run 2>&1 | head -20 fi ;; lifi|jumper) echo " LiFi/Jumper path not yet implemented; use manual links or wemix-acquire-via-lifi.js for Wemix." ;; *) echo " Unknown method: $method" ;; esac echo "" done echo "Done. See docs/03-deployment/DEPLOYER_GAS_AUTO_ROUTE_RUNBOOK.md for full steps."