#!/usr/bin/env bash # Verify the public EVM cW token deployment mesh recorded in smom-dbis-138/.env. # # Reports, per supported EVM chain: # - how many of the expected 12 cW token addresses are configured # - which token addresses are still missing # - optional on-chain bytecode presence for configured addresses when RPC + cast are available # # Usage: # bash scripts/verify/check-cw-evm-deployment-mesh.sh # bash scripts/verify/check-cw-evm-deployment-mesh.sh --json # # Exit codes: # 0 = every tracked EVM chain has all 12 cW token addresses configured and no code gaps were found # 1 = one or more chains are partial, missing, or have code gaps set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" SMOM_ROOT="${PROJECT_ROOT}/smom-dbis-138" OUTPUT_JSON=0 for arg in "$@"; do case "$arg" in --json) OUTPUT_JSON=1 ;; *) echo "Unknown argument: $arg" >&2 exit 2 ;; esac done if [[ -f "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1090 source "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" load_deployment_env --repo-root "$SMOM_ROOT" else set -a # shellcheck disable=SC1090 source "$SMOM_ROOT/.env" set +a fi have_cast=0 if command -v cast >/dev/null 2>&1; then have_cast=1 fi rpc_for_chain() { local chain_key="$1" case "$chain_key" in MAINNET) printf '%s\n' "${ETH_MAINNET_RPC_URL:-${ETHEREUM_MAINNET_RPC:-}}" ;; CRONOS) printf '%s\n' "${CRONOS_CW_VERIFY_RPC_URL:-${CRONOS_RPC_URL:-${CRONOS_RPC:-https://cronos-evm-rpc.publicnode.com}}}" ;; BSC) printf '%s\n' "${BSC_RPC_URL:-}" ;; POLYGON) printf '%s\n' "${POLYGON_MAINNET_RPC:-${POLYGON_RPC_URL:-}}" ;; GNOSIS) printf '%s\n' "${GNOSIS_RPC:-${GNOSIS_RPC_URL:-}}" ;; AVALANCHE) printf '%s\n' "${AVALANCHE_RPC_URL:-}" ;; BASE) printf '%s\n' "${BASE_MAINNET_RPC:-${BASE_RPC_URL:-}}" ;; ARBITRUM) printf '%s\n' "${ARBITRUM_MAINNET_RPC:-${ARBITRUM_RPC_URL:-}}" ;; OPTIMISM) printf '%s\n' "${OPTIMISM_MAINNET_RPC:-${OPTIMISM_RPC_URL:-}}" ;; CELO) printf '%s\n' "${CELO_RPC:-${CELO_MAINNET_RPC:-}}" ;; WEMIX) printf '%s\n' "${WEMIX_RPC:-${WEMIX_MAINNET_RPC:-}}" ;; *) printf '\n' ;; esac } TOKENS=(USDT USDC EURC EURT GBPC GBPT AUDC JPYC CHFC CADC XAUC XAUT) CHAIN_SPECS=( "MAINNET:1:Ethereum Mainnet" "CRONOS:25:Cronos" "BSC:56:BSC" "POLYGON:137:Polygon" "GNOSIS:100:Gnosis" "AVALANCHE:43114:Avalanche" "BASE:8453:Base" "ARBITRUM:42161:Arbitrum" "OPTIMISM:10:Optimism" "CELO:42220:Celo" "WEMIX:1111:Wemix" ) chains_json='[]' full_set_chains=0 partial_chains=0 total_missing_tokens=0 total_code_gaps=0 total_checked_addresses=0 total_code_verified=0 for spec in "${CHAIN_SPECS[@]}"; do IFS=":" read -r chain_key chain_id chain_name <<<"$spec" rpc="$(rpc_for_chain "$chain_key")" set_count=0 missing_count=0 code_verified=0 code_gaps=0 missing_list='[]' configured_list='[]' for token in "${TOKENS[@]}"; do var="CW${token}_${chain_key}" addr="${!var:-}" if [[ -z "$addr" ]]; then missing_count=$((missing_count + 1)) missing_list="$(jq -c --arg var "$var" '. + [$var]' <<<"$missing_list")" continue fi set_count=$((set_count + 1)) total_checked_addresses=$((total_checked_addresses + 1)) code_present=null if (( have_cast == 1 )) && [[ -n "$rpc" ]]; then code="$(cast code "$addr" --rpc-url "$rpc" 2>/dev/null || true)" if [[ -n "$code" && "$code" != "0x" ]]; then code_present=true code_verified=$((code_verified + 1)) total_code_verified=$((total_code_verified + 1)) else code_present=false code_gaps=$((code_gaps + 1)) total_code_gaps=$((total_code_gaps + 1)) fi fi configured_list="$(jq -c --arg var "$var" --arg addr "$addr" --argjson codePresent "$code_present" \ '. + [{envKey: $var, address: $addr, codePresent: $codePresent}]' <<<"$configured_list")" done if (( missing_count == 0 )); then full_set_chains=$((full_set_chains + 1)) status="complete" else partial_chains=$((partial_chains + 1)) total_missing_tokens=$((total_missing_tokens + missing_count)) status="partial" fi chains_json="$(jq -c \ --arg chainKey "$chain_key" \ --arg chainName "$chain_name" \ --argjson chainId "$chain_id" \ --arg status "$status" \ --arg rpc "${rpc:-}" \ --argjson expectedCount "${#TOKENS[@]}" \ --argjson configuredCount "$set_count" \ --argjson missingCount "$missing_count" \ --argjson codeVerifiedCount "$code_verified" \ --argjson codeGapCount "$code_gaps" \ --argjson configured "$configured_list" \ --argjson missing "$missing_list" \ '. + [{ chainKey: $chainKey, chainName: $chainName, chainId: $chainId, status: $status, rpcUrl: (if $rpc == "" then null else $rpc end), expectedCount: $expectedCount, configuredCount: $configuredCount, missingCount: $missingCount, codeVerifiedCount: $codeVerifiedCount, codeGapCount: $codeGapCount, configured: $configured, missing: $missing }]' <<<"$chains_json")" done if (( OUTPUT_JSON == 1 )); then jq -n \ --argjson chains "$chains_json" \ --argjson totalChains "${#CHAIN_SPECS[@]}" \ --argjson expectedPerChain "${#TOKENS[@]}" \ --argjson fullSetChains "$full_set_chains" \ --argjson partialChains "$partial_chains" \ --argjson totalMissingTokens "$total_missing_tokens" \ --argjson totalCheckedAddresses "$total_checked_addresses" \ --argjson totalCodeVerified "$total_code_verified" \ --argjson totalCodeGaps "$total_code_gaps" \ '{ summary: { totalChains: $totalChains, expectedPerChain: $expectedPerChain, fullSetChains: $fullSetChains, partialChains: $partialChains, totalMissingTokens: $totalMissingTokens, totalCheckedAddresses: $totalCheckedAddresses, totalCodeVerified: $totalCodeVerified, totalCodeGaps: $totalCodeGaps }, chains: $chains }' exit 0 fi echo "=== cW EVM Deployment Mesh ===" for spec in "${CHAIN_SPECS[@]}"; do IFS=":" read -r chain_key _chain_id chain_name <<<"$spec" line="$(jq -r --arg k "$chain_key" ' .chains[] | select(.chainKey == $k) | "\(.chainName): configured=\(.configuredCount)/\(.expectedCount) missing=\(.missingCount) codeVerified=\(.codeVerifiedCount) codeGaps=\(.codeGapCount) status=\(.status) missingKeys=\((.missing | join(",")))" ' <(jq -n --argjson chains "$chains_json" '{chains:$chains}'))" echo "$line" done echo "Summary: full_sets=$full_set_chains partial_sets=$partial_chains missing_tokens=$total_missing_tokens checked=$total_checked_addresses code_verified=$total_code_verified code_gaps=$total_code_gaps" if (( partial_chains > 0 || total_code_gaps > 0 )); then exit 1 fi