- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains - Omit embedded publish git dirs and empty placeholders from index Made-with: Cursor
228 lines
7.7 KiB
Bash
Executable File
228 lines
7.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Mainnet PMM peg + bot readiness checks for recorded chain-1 pools.
|
|
#
|
|
# - Confirms RPC is Ethereum mainnet (chain id 1)
|
|
# - Reads pools from cross-chain-pmm-lps/config/deployment-status.json
|
|
# (pmmPools hub rows + pmmPoolsVolatile for cW/TRUU when poolAddress is set)
|
|
# - Verifies DODO_PMM_INTEGRATION_MAINNET mapping and non-zero reserves
|
|
# - For USD-class cW vs USDC/USDT pools, compares reserve imbalance (bps) to peg-bands.json
|
|
#
|
|
# Env:
|
|
# ETHEREUM_MAINNET_RPC, DODO_PMM_INTEGRATION_MAINNET (required)
|
|
# MIN_POOL_RESERVE_RAW — minimum per-leg reserve (default: 1)
|
|
# PMM_TRUU_BASE_TOKEN, PMM_TRUU_QUOTE_TOKEN — optional extra pair to verify (ERC-20 addresses)
|
|
# SKIP_EXIT=1 — exit 0 even when checks fail (reporting mode)
|
|
#
|
|
# See: docs/03-deployment/MAINNET_PMM_TRUU_CWUSD_PEG_AND_BOT_RUNBOOK.md
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
|
|
STATUS_JSON="${REPO_ROOT}/cross-chain-pmm-lps/config/deployment-status.json"
|
|
PEG_JSON="${REPO_ROOT}/cross-chain-pmm-lps/config/peg-bands.json"
|
|
|
|
source "${REPO_ROOT}/smom-dbis-138/scripts/load-env.sh" >/dev/null 2>&1 || true
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || {
|
|
echo "[fail] missing required command: $1" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
require_cmd cast
|
|
require_cmd jq
|
|
|
|
RPC_URL="${ETHEREUM_MAINNET_RPC:-}"
|
|
INTEGRATION="${DODO_PMM_INTEGRATION_MAINNET:-}"
|
|
MIN_POOL_RESERVE_RAW="${MIN_POOL_RESERVE_RAW:-1}"
|
|
SKIP_EXIT="${SKIP_EXIT:-0}"
|
|
|
|
if [[ -z "$RPC_URL" || -z "$INTEGRATION" ]]; then
|
|
echo "[fail] ETHEREUM_MAINNET_RPC and DODO_PMM_INTEGRATION_MAINNET are required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$STATUS_JSON" ]]; then
|
|
echo "[fail] missing $STATUS_JSON" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$PEG_JSON" ]]; then
|
|
echo "[fail] missing $PEG_JSON" >&2
|
|
exit 1
|
|
fi
|
|
|
|
failures=0
|
|
warnings=0
|
|
|
|
normal_max_bps="$(jq -r '.usdPegged.normalBps.max // 25' "$PEG_JSON")"
|
|
circuit_bps="$(jq -r '.usdPegged.circuitBreakBps // 200' "$PEG_JSON")"
|
|
|
|
is_usd_pegged_base() {
|
|
local sym="$1"
|
|
jq -e --arg s "$sym" '.usdPegged.tokens | index($s) != null' "$PEG_JSON" >/dev/null 2>&1
|
|
}
|
|
|
|
chain_id="$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null | head -1 | tr -d '\r' || true)"
|
|
if [[ "$chain_id" != "1" ]]; then
|
|
echo "[fail] expected eth_chainId 1, got '${chain_id:-unknown}'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "=== Mainnet PMM peg / bot readiness ==="
|
|
echo "RPC: $RPC_URL"
|
|
echo "Integration: $INTEGRATION"
|
|
echo "Min reserve (raw per leg): $MIN_POOL_RESERVE_RAW"
|
|
echo "USD peg bands (from peg-bands.json): normal max ${normal_max_bps} bps, circuit ${circuit_bps} bps"
|
|
echo
|
|
|
|
check_pool_row() {
|
|
local base_sym="$1"
|
|
local quote_sym="$2"
|
|
local expected_pool="$3"
|
|
local label="${base_sym}/${quote_sym}"
|
|
|
|
local base_addr
|
|
base_addr="$(jq -r --arg b "$base_sym" '.chains["1"].cwTokens[$b] // empty' "$STATUS_JSON")"
|
|
local quote_addr
|
|
if [[ "$quote_sym" == "TRUU" ]]; then
|
|
quote_addr="$(jq -r '.chains["1"].anchorAddresses.TRUU // empty' "$STATUS_JSON")"
|
|
else
|
|
quote_addr="$(jq -r --arg q "$quote_sym" '.chains["1"].anchorAddresses[$q] // empty' "$STATUS_JSON")"
|
|
fi
|
|
|
|
if [[ -z "$base_addr" || -z "$quote_addr" ]]; then
|
|
echo "[fail] $label — could not resolve token address (base=$base_addr quote=$quote_addr)" >&2
|
|
failures=$((failures + 1))
|
|
return
|
|
fi
|
|
|
|
local mapped
|
|
mapped="$(cast call "$INTEGRATION" 'pools(address,address)(address)' "$base_addr" "$quote_addr" --rpc-url "$RPC_URL" 2>/dev/null | awk '{print tolower($1)}' || true)"
|
|
local exp_lower
|
|
exp_lower="$(printf '%s' "$expected_pool" | tr '[:upper:]' '[:lower:]')"
|
|
|
|
if [[ "$mapped" != "$exp_lower" ]]; then
|
|
echo "[fail] $label — integration mapping mismatch: expected $expected_pool got ${mapped:-empty}" >&2
|
|
failures=$((failures + 1))
|
|
return
|
|
fi
|
|
|
|
local reserve_output
|
|
reserve_output="$(cast call "$expected_pool" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_URL" 2>/dev/null || true)"
|
|
local r0 r1
|
|
r0="$(printf '%s\n' "$reserve_output" | sed -n '1p' | awk '{print $1}')"
|
|
r1="$(printf '%s\n' "$reserve_output" | sed -n '2p' | awk '{print $1}')"
|
|
|
|
if [[ -z "$r0" || -z "$r1" ]]; then
|
|
echo "[fail] $label — could not read reserves" >&2
|
|
failures=$((failures + 1))
|
|
return
|
|
fi
|
|
|
|
if [[ "$r0" -lt "$MIN_POOL_RESERVE_RAW" || "$r1" -lt "$MIN_POOL_RESERVE_RAW" ]]; then
|
|
echo "[fail] $label — reserves below MIN_POOL_RESERVE_RAW ($r0 / $r1)" >&2
|
|
failures=$((failures + 1))
|
|
return
|
|
fi
|
|
|
|
local imb_bps=0
|
|
local peg_info=""
|
|
local peg_circuit_failed=0
|
|
if is_usd_pegged_base "$base_sym" && [[ "$quote_sym" == "USDC" || "$quote_sym" == "USDT" ]]; then
|
|
local max_r
|
|
if [[ "$r0" -ge "$r1" ]]; then
|
|
max_r="$r0"
|
|
else
|
|
max_r="$r1"
|
|
fi
|
|
if [[ "$max_r" -eq 0 ]]; then
|
|
imb_bps=10000
|
|
else
|
|
local diff
|
|
if [[ "$r0" -ge "$r1" ]]; then
|
|
diff=$((r0 - r1))
|
|
else
|
|
diff=$((r1 - r0))
|
|
fi
|
|
imb_bps=$((10000 * diff / max_r))
|
|
fi
|
|
peg_info="imbalance_bps=${imb_bps}"
|
|
if [[ "$imb_bps" -gt "$circuit_bps" ]]; then
|
|
echo "[fail] $label — reserve imbalance ${imb_bps} bps exceeds circuit ${circuit_bps} bps (r0=$r0 r1=$r1)" >&2
|
|
failures=$((failures + 1))
|
|
peg_circuit_failed=1
|
|
elif [[ "$imb_bps" -gt "$normal_max_bps" ]]; then
|
|
echo "[warn] $label — reserve imbalance ${imb_bps} bps exceeds normal band max ${normal_max_bps} bps (r0=$r0 r1=$r1)" >&2
|
|
warnings=$((warnings + 1))
|
|
fi
|
|
fi
|
|
|
|
if [[ "$peg_circuit_failed" -eq 0 ]]; then
|
|
echo "- $label pool=$expected_pool reserves=$r0/$r1 ${peg_info:+$peg_info}"
|
|
fi
|
|
}
|
|
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
base_sym="${line%%|*}"
|
|
rest="${line#*|}"
|
|
quote_sym="${rest%%|*}"
|
|
pool_addr="${rest##*|}"
|
|
check_pool_row "$base_sym" "$quote_sym" "$pool_addr"
|
|
done < <(jq -r '.chains["1"].pmmPools[]? | "\(.base)|\(.quote)|\(.poolAddress)"' "$STATUS_JSON" 2>/dev/null || true)
|
|
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
base_sym="${line%%|*}"
|
|
rest="${line#*|}"
|
|
quote_sym="${rest%%|*}"
|
|
pool_addr="${rest##*|}"
|
|
check_pool_row "$base_sym" "$quote_sym" "$pool_addr"
|
|
done < <(jq -r '
|
|
.chains["1"].pmmPoolsVolatile[]?
|
|
| select(
|
|
(.poolAddress // "") != ""
|
|
and ((.poolAddress | ascii_downcase) != "0x0000000000000000000000000000000000000000")
|
|
)
|
|
| "\(.base)|\(.quote)|\(.poolAddress)"
|
|
' "$STATUS_JSON" 2>/dev/null || true)
|
|
|
|
if [[ -n "${PMM_TRUU_BASE_TOKEN:-}" && -n "${PMM_TRUU_QUOTE_TOKEN:-}" ]]; then
|
|
echo
|
|
echo "=== Optional TRUU PMM pair (PMM_TRUU_BASE_TOKEN / PMM_TRUU_QUOTE_TOKEN) ==="
|
|
tpool="$(cast call "$INTEGRATION" 'pools(address,address)(address)' "$PMM_TRUU_BASE_TOKEN" "$PMM_TRUU_QUOTE_TOKEN" --rpc-url "$RPC_URL" 2>/dev/null | awk '{print $1}')"
|
|
if [[ "$tpool" == "0x0000000000000000000000000000000000000000" ]]; then
|
|
echo "[warn] No pool registered for TRUU pair (base=$PMM_TRUU_BASE_TOKEN quote=$PMM_TRUU_QUOTE_TOKEN)" >&2
|
|
warnings=$((warnings + 1))
|
|
else
|
|
tres="$(cast call "$tpool" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_URL" 2>/dev/null || true)"
|
|
tr0="$(printf '%s\n' "$tres" | sed -n '1p' | awk '{print $1}')"
|
|
tr1="$(printf '%s\n' "$tres" | sed -n '2p' | awk '{print $1}')"
|
|
if [[ -z "$tr0" || -z "$tr1" || "$tr0" -lt "$MIN_POOL_RESERVE_RAW" || "$tr1" -lt "$MIN_POOL_RESERVE_RAW" ]]; then
|
|
echo "[warn] TRUU PMM pool $tpool has weak or unreadable reserves ($tr0 / $tr1)" >&2
|
|
warnings=$((warnings + 1))
|
|
else
|
|
echo "- TRUU PMM pool=$tpool reserves=$tr0/$tr1"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
if (( failures > 0 )); then
|
|
echo "[fail] $failures hard failure(s), $warnings warning(s)." >&2
|
|
if [[ "$SKIP_EXIT" == "1" ]]; then
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
fi
|
|
if (( warnings > 0 )); then
|
|
echo "[ok] checks passed with $warnings warning(s)."
|
|
exit 0
|
|
fi
|
|
echo "[ok] all checks passed."
|
|
exit 0
|