#!/usr/bin/env bash # Deploy WETH9/WETH10 + CCIP bridges (and optionally Cronos D-WIN W) to all blockchains # unless a canonical/pre-existing deployment is already present in .env. # # Deploys: # - WETH9, WETH10, CCIPWETH9Bridge, CCIPWETH10Bridge (via DeployAll.s.sol) on each chain # where WETH9_ and WETH10_ are not both set. # - On Cronos (25): optionally ISO-4217 W system (USDW, EURW, ...) if not already deployed. # - With --deploy-c: cUSDT/cUSDC (and optional c*) on each chain where CUSDT_/CUSDC_ unset (via DeployCompliantFiatTokensForChain.s.sol). # - With --deploy-cw: cWUSDT/cWUSDC on each chain where CWUSDT_ unset (via DeployCWTokens.s.sol; set CW_BRIDGE_ADDRESS or CW_BRIDGE_). # - Chain 651940 (ALL Mainnet): env validation only (check AUSDT_ADDRESS_651940 set); no token deploy from this repo. # # Skips: # - Ethereum Mainnet (1): uses canonical WETH from .env (WETH9_MAINNET, WETH10_MAINNET). # - Any chain where both WETH9_* and WETH10_* are already set in .env. # - Chain 138: not in DeployAll; compliant tokens (c*) are deployed separately on 138. # # Usage: # cd smom-dbis-138 && ./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh [OPTIONS] # # Options: # --dry-run Print commands only; do not broadcast. # --chain 25 56 137 Deploy only to these chain IDs (default: all supported). # --no-iso4217 Do not deploy ISO-4217 W system on Cronos even if missing. # --iso4217-only Only run Cronos ISO-4217 W deploy (skip DeployAll). # --deploy-c Deploy cUSDT/cUSDC (and optional c*) on chains where CUSDT_/CUSDC_ unset (skip 138, 1). # --deploy-cw Deploy cWUSDT/cWUSDC on chains where CWUSDT_ unset; requires CW_BRIDGE_ADDRESS or CW_BRIDGE_ in .env. # # Requires: .env with PRIVATE_KEY; per-chain RPC and CCIP vars for chains you deploy to. # See: docs/11-references/TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 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 DRY_RUN=false CHAINS_FILTER="" NO_ISO4217=false ISO4217_ONLY=false DEPLOY_C=false DEPLOY_CW=false while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN=true; shift ;; --no-iso4217) NO_ISO4217=true; shift ;; --iso4217-only) ISO4217_ONLY=true; shift ;; --deploy-c) DEPLOY_C=true; shift ;; --deploy-cw) DEPLOY_CW=true; shift ;; --chain) shift CHAINS_FILTER="$*" break ;; *) shift ;; esac done # Chain ID : Name : RPC env var (primary) # DeployAll.s.sol supports: 1, 25, 56, 137, 100, 43114, 8453, 42161, 10. 651940 = env validation only. # Celo / Wemix are included here for c* / cW* deployment even though their WETH/bridge deploy # flow is handled separately via deploy-bridges-config-ready-chains.sh. ALL_CHAINS="1:Mainnet:ETH_MAINNET_RPC_URL 25:Cronos:CRONOS_RPC_URL 56:BSC:BSC_RPC_URL 137:Polygon:POLYGON_RPC_URL 100:Gnosis:GNOSIS_RPC_URL 43114:Avalanche:AVALANCHE_RPC_URL 8453:Base:BASE_RPC_URL 42161:Arbitrum:ARBITRUM_RPC_URL 10:Optimism:OPTIMISM_RPC_URL 42220:Celo:CELO_RPC 1111:Wemix:WEMIX_RPC 651940:ALL:CHAIN_651940_RPC" # Fallback RPC env names (some scripts use different names) fallback_rpc() { local chain_id="$1" local rpc_var="$2" local rpc="${!rpc_var:-}" if [[ -z "$rpc" ]]; then case "$chain_id" in 1) rpc="${ETHEREUM_MAINNET_RPC:-${ETH_MAINNET_RPC_URL:-}}";; 25) rpc="${CRONOS_RPC:-}";; 56) rpc="${BSC_RPC_URL:-}";; 137) rpc="${POLYGON_MAINNET_RPC:-}";; 100) rpc="${GNOSIS_RPC:-}";; 43114) rpc="${AVALANCHE_RPC_URL:-}";; 8453) rpc="${BASE_MAINNET_RPC:-}";; 42161) rpc="${ARBITRUM_MAINNET_RPC:-}";; 10) rpc="${OPTIMISM_MAINNET_RPC:-}";; 42220) rpc="${CELO_RPC:-${CELO_MAINNET_RPC:-}}";; 1111) rpc="${WEMIX_RPC:-${WEMIX_MAINNET_RPC:-}}";; 651940) rpc="${CHAIN_651940_RPC:-${ALL_MAINNET_RPC:-}}";; esac fi echo "$rpc" } is_canonical_present() { local weth9_var="$1" local weth10_var="$2" local w9="${!weth9_var:-}" local w10="${!weth10_var:-}" w9="${w9//0x/}" w10="${w10//0x/}" [[ -n "$w9" && "${#w9}" -ge 40 && "$w9" != "0000000000000000000000000000000000000000" ]] && \ [[ -n "$w10" && "${#w10}" -ge 40 && "$w10" != "0000000000000000000000000000000000000000" ]] && return 0 return 1 } run_cmd() { if $DRY_RUN; then echo " [DRY-RUN] $*" else eval "$@" || return 1 fi } # ---------- DeployAll (WETH9, WETH10, CCIP bridges) per chain ---------- run_deploy_all() { local chain_id="$1" local name="$2" local rpc_var="$3" if [[ "$chain_id" == "651940" ]]; then echo " Skip $name (chain 651940): DeployAll not supported; env validation only." return 0 fi if [[ "$chain_id" == "42220" || "$chain_id" == "1111" ]]; then echo " Skip $name (chain $chain_id): WETH/bridge deploy handled by deploy-bridges-config-ready-chains.sh; c*/cW* phases may still run." return 0 fi local rpc rpc=$(fallback_rpc "$chain_id" "$rpc_var") if [[ -z "$rpc" ]]; then echo " Skip $name (chain $chain_id): RPC not set ($rpc_var)." return 0 fi local weth9_var="WETH9_MAINNET" weth10_var="WETH10_MAINNET" case "$chain_id" in 1) weth9_var="WETH9_MAINNET"; weth10_var="WETH10_MAINNET" ;; 25) weth9_var="WETH9_CRONOS"; weth10_var="WETH10_CRONOS" ;; 56) weth9_var="WETH9_BSC"; weth10_var="WETH10_BSC" ;; 137) weth9_var="WETH9_POLYGON"; weth10_var="WETH10_POLYGON" ;; 100) weth9_var="WETH9_GNOSIS"; weth10_var="WETH10_GNOSIS" ;; 43114) weth9_var="WETH9_AVALANCHE"; weth10_var="WETH10_AVALANCHE" ;; 8453) weth9_var="WETH9_BASE"; weth10_var="WETH10_BASE" ;; 42161) weth9_var="WETH9_ARBITRUM"; weth10_var="WETH10_ARBITRUM" ;; 10) weth9_var="WETH9_OPTIMISM"; weth10_var="WETH10_OPTIMISM" ;; *) echo " Unsupported chain ID $chain_id"; return 1 ;; esac # Mainnet: use canonical WETH from .env; DeployAll only deploys CCIPLogger (placeholder). Skip to avoid requiring env. if [[ "$chain_id" == "1" ]]; then if is_canonical_present "$weth9_var" "$weth10_var"; then echo " Skip $name (chain $chain_id): canonical WETH9/WETH10 already set." return 0 fi echo " Skip $name (chain $chain_id): set WETH9_MAINNET and WETH10_MAINNET in .env for canonical WETH; DeployAll on Mainnet does not deploy tokens." return 0 fi if is_canonical_present "$weth9_var" "$weth10_var"; then echo " Skip $name (chain $chain_id): WETH9/WETH10 already set in .env." return 0 fi echo " Deploying WETH9, WETH10, CCIP bridges on $name (chain $chain_id)..." local gas_opts="--legacy" run_cmd "forge script script/DeployAll.s.sol:DeployAll --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" $gas_opts -vvv" || true echo " → Set WETH9_${name^^}, WETH10_${name^^}, CCIPWETH9_BRIDGE_${name^^}, CCIPWETH10_BRIDGE_${name^^} in .env from script output." } # ---------- ISO-4217 W (Cronos): deploy only if USDW not already deployed ---------- run_iso4217_cronos() { if $NO_ISO4217; then echo " Skip Cronos ISO-4217 W (--no-iso4217)." return 0 fi local rpc rpc=$(fallback_rpc 25 "CRONOS_RPC_URL") [[ -z "$rpc" ]] && rpc="${CRONOS_RPC:-}" if [[ -z "$rpc" ]]; then echo " Skip Cronos ISO-4217 W: CRONOS_RPC_URL / CRONOS_RPC not set." return 0 fi local usdw_addr="0x948690147D2e50ffe50C5d38C14125aD6a9FA036" local code_len code_len=$(cast code "$usdw_addr" --rpc-url "$rpc" 2>/dev/null | wc -c) if [[ -n "$code_len" && "$code_len" -gt 10 ]]; then echo " Skip Cronos ISO-4217 W: USDW already deployed at $usdw_addr." return 0 fi echo " Deploying ISO-4217 W system on Cronos (25)..." run_cmd "forge script script/deploy/iso4217w/DeployISO4217WSystem.s.sol:DeployISO4217WSystem --rpc-url \"$rpc\" --chain-id 25 --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true echo " → Record MintController, TokenRegistry, USDW, EURW, ... addresses from output; add to .env / docs." } # ---------- c* (cUSDT, cUSDC) on other chains: DeployCompliantFiatTokensForChain ---------- run_deploy_c() { local chain_id="$1" local name="$2" local rpc_var="$3" [[ "$chain_id" == "138" || "$chain_id" == "1" ]] && return 0 local rpc rpc=$(fallback_rpc "$chain_id" "$rpc_var") if [[ -z "$rpc" ]]; then return 0; fi local cusdt_var="CUSDT_${name^^}" cusdc_var="CUSDC_${name^^}" local cusdt_val="${!cusdt_var:-}" cusdc_val="${!cusdc_var:-}" cusdt_val="${cusdt_val//0x/}"; cusdc_val="${cusdc_val//0x/}" if [[ -n "$cusdt_val" && "${#cusdt_val}" -ge 40 ]] && [[ -n "$cusdc_val" && "${#cusdc_val}" -ge 40 ]]; then echo " Skip c* on $name (chain $chain_id): CUSDT_${name^^} and CUSDC_${name^^} already set." return 0 fi echo " Deploying cUSDT/cUSDC on $name (chain $chain_id)..." run_cmd "forge script script/deploy/DeployCompliantFiatTokensForChain.s.sol:DeployCompliantFiatTokensForChain --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true echo " → Set CUSDT_${name^^}, CUSDC_${name^^} in .env from script output." } # ---------- cW* (all 12: cWUSDT, cWUSDC, cWEURC, cWEURT, cWGBPC, cWGBPT, cWAUDC, cWJPYC, cWCHFC, cWCADC, cWXAUC, cWXAUT): DeployCWTokens ---------- run_deploy_cw() { local chain_id="$1" local name="$2" local rpc_var="$3" local rpc rpc=$(fallback_rpc "$chain_id" "$rpc_var") if [[ -z "$rpc" ]]; then return 0; fi local bridge_var="CW_BRIDGE_${name^^}" local ccip_bridge_var="CCIPWETH9_BRIDGE_${name^^}" local bridge="${!bridge_var:-${CW_BRIDGE_ADDRESS:-}}" if [[ -z "$bridge" || "$bridge" == "0x0000000000000000000000000000000000000000" ]]; then bridge="${!ccip_bridge_var:-}" fi if [[ -z "$bridge" || "$bridge" == "0x"*"0000000000000000000000000000000000000000" ]]; then echo " Skip cW* on $name (chain $chain_id): set CW_BRIDGE_ADDRESS / CW_BRIDGE_${name^^} or deploy/configure CCIPWETH9_BRIDGE_${name^^}." return 0 fi local cw_var="CWUSDT_${name^^}" local cw_val="${!cw_var:-}" cw_val="${cw_val//0x/}" local deploy_opts="" if [[ -n "$cw_val" && "${#cw_val}" -ge 40 ]]; then echo " Deploying remaining cW* (cWEURC..cWXAUT) on $name (chain $chain_id) (bridge $bridge)..." deploy_opts="DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0" else echo " Deploying all cW* (12 tokens) on $name (chain $chain_id) (bridge $bridge)..." fi local gas_opt="" [[ "$chain_id" == "42161" && -n "${ARBITRUM_GAS_PRICE:-}" ]] && gas_opt="--with-gas-price ${ARBITRUM_GAS_PRICE}" run_cmd "${deploy_opts:+$deploy_opts }CW_BRIDGE_ADDRESS=$bridge CW_STRICT_MODE=${CW_STRICT_MODE:-1} CW_FREEZE_OPERATIONAL_ROLES=${CW_FREEZE_OPERATIONAL_ROLES:-1} forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy ${gas_opt} -vvv" || true echo " → Set CWUSDT_*, CWUSDC_*, CWEURC_*, CWEURT_*, CWGBPC_*, CWGBPT_*, CWAUDC_*, CWJPYC_*, CWCHFC_*, CWCADC_*, CWXAUC_*, CWXAUT_* in .env from script output." } # ---------- 651940 (ALL Mainnet): env validation only ---------- run_651940_validate() { local rpc rpc=$(fallback_rpc 651940 "CHAIN_651940_RPC") if [[ -z "$rpc" ]]; then echo " Skip ALL (651940): CHAIN_651940_RPC not set." return 0 fi local ausdt_var="AUSDT_ADDRESS_651940" local ausdt_val="${!ausdt_var:-}" if [[ -z "$ausdt_val" || "$ausdt_val" == "0x0000000000000000000000000000000000000000" ]]; then echo " ALL (651940): Set AUSDT_ADDRESS_651940 in .env (ecosystem token; not deployed by this script)." else echo " ALL (651940): AUSDT_ADDRESS_651940 set." fi } # ---------- Main ---------- echo "==============================================" echo "Deploy tokens/WETH to all chains (skip canonical)" echo "==============================================" echo " Dry-run: $DRY_RUN" echo " Chain filter: ${CHAINS_FILTER:-all}" echo " ISO-4217 on Cronos: $(! $NO_ISO4217 && ! $ISO4217_ONLY || $ISO4217_ONLY)" echo " Deploy c* (cUSDT/cUSDC): $DEPLOY_C" echo " Deploy cW* (cWUSDT/cWUSDC): $DEPLOY_CW" echo "" if [[ -z "${PRIVATE_KEY:-}" ]]; then echo "ERROR: PRIVATE_KEY not set in .env." >&2 exit 1 fi if ! $ISO4217_ONLY; then echo "--- DeployAll (WETH9, WETH10, CCIP bridges) per chain ---" for entry in $ALL_CHAINS; do chain_id="${entry%%:*}"; rest="${entry#*:}" name="${rest%%:*}"; rpc_var="${rest#*:}" if [[ -n "$CHAINS_FILTER" ]]; then echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue fi run_deploy_all "$chain_id" "$name" "$rpc_var" done echo "" fi if ! $ISO4217_ONLY; then if [[ -z "$CHAINS_FILTER" ]] || echo "$CHAINS_FILTER" | grep -q "\b25\b"; then echo "--- Cronos: ISO-4217 W (USDW, EURW, ...) ---" run_iso4217_cronos echo "" fi else echo "--- Cronos: ISO-4217 W only ---" run_iso4217_cronos echo "" fi if $DEPLOY_C; then echo "--- Deploy c* (cUSDT/cUSDC) per chain (skip 138, 1) ---" for entry in $ALL_CHAINS; do chain_id="${entry%%:*}"; rest="${entry#*:}" name="${rest%%:*}"; rpc_var="${rest#*:}" if [[ "$chain_id" == "651940" ]]; then continue; fi if [[ -n "$CHAINS_FILTER" ]]; then echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue fi run_deploy_c "$chain_id" "$name" "$rpc_var" done echo "" fi if $DEPLOY_CW; then echo "--- Deploy cW* (cWUSDT/cWUSDC) per chain ---" for entry in $ALL_CHAINS; do chain_id="${entry%%:*}"; rest="${entry#*:}" name="${rest%%:*}"; rpc_var="${rest#*:}" if [[ "$chain_id" == "651940" ]]; then continue; fi if [[ -n "$CHAINS_FILTER" ]]; then echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue fi run_deploy_cw "$chain_id" "$name" "$rpc_var" done echo "" fi echo "--- Chain 651940 (ALL Mainnet) env validation ---" for entry in $ALL_CHAINS; do chain_id="${entry%%:*}"; rest="${entry#*:}" name="${rest%%:*}"; rpc_var="${rest#*:}" if [[ "$chain_id" != "651940" ]]; then continue; fi if [[ -n "$CHAINS_FILTER" ]]; then echo "$CHAINS_FILTER" | grep -q "\b651940\b" || continue fi run_651940_validate break done echo "" echo "==============================================" echo "Done. Update .env with deployed addresses; see TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md." echo "=============================================="