#!/usr/bin/env bash set -euo pipefail # Build an operator-safe stabilization plan for the live Mainnet cW/USD rails. # Reads wallet balances and current DODO PMM reserves, then prints: # - current live state # - suggested micro-support swap sizes # - reserve shortfalls versus a target matched-rail depth # - exact dry-run commands for the existing swap helper # # Example: # bash scripts/deployment/plan-mainnet-cw-stabilization.sh # TARGET_MATCHED_QUOTE_UNITS=1000 MICRO_BPS=25 bash scripts/deployment/plan-mainnet-cw-stabilization.sh SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" source "${PROJECT_ROOT}/smom-dbis-138/scripts/load-env.sh" >/dev/null 2>&1 require_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "[fail] missing required command: $1" >&2 exit 1 } } require_cmd cast require_cmd python3 RPC_URL="${ETHEREUM_MAINNET_RPC:-}" PRIVATE_KEY="${PRIVATE_KEY:-}" if [[ -z "$RPC_URL" || -z "$PRIVATE_KEY" ]]; then echo "[fail] ETHEREUM_MAINNET_RPC and PRIVATE_KEY are required" >&2 exit 1 fi DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" MICRO_BPS="${MICRO_BPS:-25}" REBALANCE_BPS="${REBALANCE_BPS:-100}" TARGET_MATCHED_QUOTE_UNITS="${TARGET_MATCHED_QUOTE_UNITS:-1000}" CWUSDT_MAINNET="${CWUSDT_MAINNET:-0xaF5017d0163ecb99D9B5D94e3b4D7b09Af44D8AE}" CWUSDC_MAINNET="${CWUSDC_MAINNET:-0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a}" USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" USDT_MAINNET="0xdAC17F958D2ee523a2206206994597C13D831ec7" POOL_CWUSDT_USDC_MAINNET="${POOL_CWUSDT_USDC_MAINNET:-0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2}" POOL_CWUSDC_USDC_MAINNET="${POOL_CWUSDC_USDC_MAINNET:-0x69776fc607e9edA8042e320e7e43f54d06c68f0E}" POOL_CWUSDT_USDT_MAINNET="${POOL_CWUSDT_USDT_MAINNET:-0x79156F6B7bf71a1B72D78189B540A89A6C13F6FC}" POOL_CWUSDC_USDT_MAINNET="${POOL_CWUSDC_USDT_MAINNET:-0xCC0fd27A40775c9AfcD2BBd3f7c902b0192c247A}" to_units() { python3 - "$1" <<'PY' import sys raw = int(sys.argv[1]) print(f"{raw / 1_000_000:.6f}") PY } from_units_raw() { python3 - "$1" <<'PY' import sys units = float(sys.argv[1]) print(int(round(units * 1_000_000))) PY } read_balance() { cast call "$1" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL" | awk '{print $1}' } read_mapping_pool() { cast call "${DODO_PMM_INTEGRATION_MAINNET:-}" 'pools(address,address)(address)' "$1" "$2" --rpc-url "$RPC_URL" 2>/dev/null | awk '{print $1}' } resolve_pool() { local configured="$1" local base_token="$2" local quote_token="$3" local mapped mapped="$(read_mapping_pool "$base_token" "$quote_token")" if [[ -n "$mapped" && "$mapped" != "0x0000000000000000000000000000000000000000" ]]; then printf '%s\n' "$mapped" else printf '%s\n' "$configured" fi } read_reserves() { local output output="$(cast call "$1" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_URL")" printf '%s\n' "$output" | sed -n '1p' | awk '{print $1}' printf '%s\n' "$output" | sed -n '2p' | awk '{print $1}' } suggest_trade_raw() { python3 - "$1" "$2" <<'PY' import sys reserve = int(sys.argv[1]) bps = int(sys.argv[2]) trade = max(1, reserve * bps // 10_000) print(trade) PY } POOL_CWUSDT_USDC_MAINNET="$(resolve_pool "$POOL_CWUSDT_USDC_MAINNET" "$CWUSDT_MAINNET" "$USDC_MAINNET")" POOL_CWUSDC_USDC_MAINNET="$(resolve_pool "$POOL_CWUSDC_USDC_MAINNET" "$CWUSDC_MAINNET" "$USDC_MAINNET")" POOL_CWUSDT_USDT_MAINNET="$(resolve_pool "$POOL_CWUSDT_USDT_MAINNET" "$CWUSDT_MAINNET" "$USDT_MAINNET")" POOL_CWUSDC_USDT_MAINNET="$(resolve_pool "$POOL_CWUSDC_USDT_MAINNET" "$CWUSDC_MAINNET" "$USDT_MAINNET")" wallet_cwusdt_raw="$(read_balance "$CWUSDT_MAINNET")" wallet_cwusdc_raw="$(read_balance "$CWUSDC_MAINNET")" wallet_usdt_raw="$(read_balance "$USDT_MAINNET")" wallet_usdc_raw="$(read_balance "$USDC_MAINNET")" read -r cwusdt_usdc_base cwusdt_usdc_quote < <(read_reserves "$POOL_CWUSDT_USDC_MAINNET" | xargs) read -r cwusdc_usdc_base cwusdc_usdc_quote < <(read_reserves "$POOL_CWUSDC_USDC_MAINNET" | xargs) read -r cwusdt_usdt_base cwusdt_usdt_quote < <(read_reserves "$POOL_CWUSDT_USDT_MAINNET" | xargs) read -r cwusdc_usdt_base cwusdc_usdt_quote < <(read_reserves "$POOL_CWUSDC_USDT_MAINNET" | xargs) target_quote_raw="$(from_units_raw "$TARGET_MATCHED_QUOTE_UNITS")" cwusdt_usdt_micro_raw="$(suggest_trade_raw "$cwusdt_usdt_quote" "$MICRO_BPS")" cwusdc_usdc_micro_raw="$(suggest_trade_raw "$cwusdc_usdc_quote" "$MICRO_BPS")" cwusdt_usdc_micro_raw="$(suggest_trade_raw "$cwusdt_usdc_quote" "$MICRO_BPS")" cwusdc_usdt_micro_raw="$(suggest_trade_raw "$cwusdc_usdt_quote" "$MICRO_BPS")" cwusdt_usdt_rebalance_raw="$(suggest_trade_raw "$cwusdt_usdt_quote" "$REBALANCE_BPS")" cwusdc_usdc_rebalance_raw="$(suggest_trade_raw "$cwusdc_usdc_quote" "$REBALANCE_BPS")" echo "=== Mainnet cW Stabilization Plan ===" echo "deployer=$DEPLOYER" echo "rpc=$RPC_URL" echo echo "Live wallet balances (6 decimals):" echo "- cWUSDT=$(to_units "$wallet_cwusdt_raw")" echo "- cWUSDC=$(to_units "$wallet_cwusdc_raw")" echo "- USDT=$(to_units "$wallet_usdt_raw")" echo "- USDC=$(to_units "$wallet_usdc_raw")" echo echo "Live matched rails (base/quote, 6 decimals):" echo "- cWUSDT/USDT: $(to_units "$cwusdt_usdt_base") / $(to_units "$cwusdt_usdt_quote")" echo "- cWUSDC/USDC: $(to_units "$cwusdc_usdc_base") / $(to_units "$cwusdc_usdc_quote")" echo "- cWUSDT/USDC: $(to_units "$cwusdt_usdc_base") / $(to_units "$cwusdt_usdc_quote")" echo "- cWUSDC/USDT: $(to_units "$cwusdc_usdt_base") / $(to_units "$cwusdc_usdt_quote")" echo echo "Recommended operating mode:" if (( wallet_usdc_raw < target_quote_raw || wallet_usdt_raw < target_quote_raw )); then echo "- meaningful matched-rail deepening is quote-constrained on mainnet today" echo "- use direct liquidity adds only after acquiring more USDC/USDT on mainnet" echo "- until then, prefer micro-support swaps only" else echo "- wallet quote inventory is sufficient for at least one ${TARGET_MATCHED_QUOTE_UNITS} unit tranche on each matched rail" echo "- deepen matched rails first, then use micro-support swaps" fi echo echo "Target matched-rail depth per quote side:" echo "- targetQuoteUnits=${TARGET_MATCHED_QUOTE_UNITS}" echo "- targetQuoteRaw=${target_quote_raw}" echo "- USDT shortfall raw=$(( target_quote_raw > wallet_usdt_raw ? target_quote_raw - wallet_usdt_raw : 0 ))" echo "- USDC shortfall raw=$(( target_quote_raw > wallet_usdc_raw ? target_quote_raw - wallet_usdc_raw : 0 ))" echo echo "Suggested micro-support sizes:" echo "- cWUSDT/USDT micro raw=${cwusdt_usdt_micro_raw} units=$(to_units "$cwusdt_usdt_micro_raw")" echo "- cWUSDC/USDC micro raw=${cwusdc_usdc_micro_raw} units=$(to_units "$cwusdc_usdc_micro_raw")" echo "- cWUSDT/USDC cross-rail micro raw=${cwusdt_usdc_micro_raw} units=$(to_units "$cwusdt_usdc_micro_raw")" echo "- cWUSDC/USDT cross-rail micro raw=${cwusdc_usdt_micro_raw} units=$(to_units "$cwusdc_usdt_micro_raw")" echo echo "Suggested matched-rail rebalance ceilings:" echo "- cWUSDT/USDT rebalance raw=${cwusdt_usdt_rebalance_raw} units=$(to_units "$cwusdt_usdt_rebalance_raw")" echo "- cWUSDC/USDC rebalance raw=${cwusdc_usdc_rebalance_raw} units=$(to_units "$cwusdc_usdc_rebalance_raw")" echo echo "Recommended sequence:" echo "1. Acquire mainnet quote inventory (USDC/USDT) before attempting meaningful depth adds." echo "2. Deepen matched rails first: cWUSDT/USDT and cWUSDC/USDC." echo "3. Use cross-quote rails only for small quote-lane rebalancing." echo "4. Keep support swaps below micro size unless reserves are materially larger." echo echo "Dry-run commands:" cat <