Files
proxmox/scripts/verify/snapshot-mainnet-cwusdc-usdc-preflight.py
defiQUG b8613905bd
Some checks failed
Deploy to Phoenix / validate (push) Failing after 15s
Deploy to Phoenix / deploy (push) Has been skipped
chore: sync workspace — configs, docs, scripts, CI, pnpm, submodules
- Submodule pins: dbis_core, cross-chain-pmm-lps, mcp-proxmox (local, push may be pending), metamask-integration, smom-dbis-138
- Atomic swap + cross-chain-pmm-lops-publish, deploy-portal workflow, phoenix deploy-targets, routing/aggregator matrices
- Docs, token-lists, forge proxy, phoenix API, runbooks, verify scripts

Made-with: Cursor
2026-04-21 22:01:33 -07:00

278 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
import os
from datetime import datetime, timezone
from decimal import Decimal, getcontext
from pathlib import Path
import re
import subprocess
import sys
getcontext().prec = 42
ROOT = Path(__file__).resolve().parents[2]
CHECKER_PATH = ROOT / "scripts" / "verify" / "check-mainnet-cwusdc-usdc-support-health.py"
POLICY_PATH = ROOT / "config" / "extraction" / "mainnet-cwusdc-usdc-support-policy.json"
ROOT_ENV_PATH = ROOT / ".env"
SMOM_ENV_PATH = ROOT / "smom-dbis-138" / ".env"
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
UINT_RE = re.compile(r"\b\d+\b")
ADDRESS_RE = re.compile(r"0x[a-fA-F0-9]{40}")
BROADCAST_RECEIVER = ROOT / "smom-dbis-138" / "broadcast" / "DeployAaveQuotePushFlashReceiver.s.sol" / "1" / "run-latest.json"
BROADCAST_MANAGER = ROOT / "smom-dbis-138" / "broadcast" / "DeployQuotePushTreasuryManager.s.sol" / "1" / "run-latest.json"
def load_json(path: Path) -> dict:
return json.loads(path.read_text())
def load_env_file(path: Path) -> dict[str, str]:
values: dict[str, str] = {}
if not path.exists():
return values
for raw_line in path.read_text().splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
values[key.strip()] = value.strip().strip('"').strip("'")
return values
def merged_env_values() -> dict[str, str]:
values: dict[str, str] = {}
values.update(load_env_file(ROOT_ENV_PATH))
values.update(load_env_file(SMOM_ENV_PATH))
return values
def resolve_env_value(key: str, env_values: dict[str, str], seen: set[str] | None = None) -> str:
if seen is None:
seen = set()
if key in seen:
return env_values.get(key, "")
seen.add(key)
value = os.environ.get(key) or env_values.get(key, "")
if value.startswith("${") and value.endswith("}"):
inner = value[2:-1]
target = inner.split(":-", 1)[0]
fallback = inner.split(":-", 1)[1] if ":-" in inner else ""
resolved = resolve_env_value(target, env_values, seen)
return resolved or fallback
return value.rstrip("\r\n")
def cast_call(rpc_url: str, target: str, signature: str, *args: str) -> str:
cmd = ["cast", "call", target, signature, *args, "--rpc-url", rpc_url]
return subprocess.check_output(cmd, text=True).strip()
def parse_uint(value: str) -> int:
matches = UINT_RE.findall(value)
if not matches:
raise ValueError(f"could not parse integer from {value!r}")
return int(matches[0])
def parse_uints(value: str, count: int) -> list[int]:
matches = [int(match) for match in UINT_RE.findall(value)]
if len(matches) < count:
raise ValueError(f"expected at least {count} integers from {value!r}")
return matches[:count]
def parse_address(value: str) -> str:
match = ADDRESS_RE.search(value)
if not match:
raise ValueError(f"could not parse address from {value!r}")
return match.group(0)
def normalize_units(raw: int, decimals: int) -> Decimal:
return Decimal(raw) / (Decimal(10) ** decimals)
def run_health_checker() -> dict:
output = subprocess.check_output(["python3", str(CHECKER_PATH)], text=True)
return json.loads(output)
def read_latest_create_address(path: Path, expected_contract_name: str) -> str:
if not path.exists():
return ""
data = load_json(path)
for tx in reversed(data.get("transactions", [])):
if tx.get("transactionType") == "CREATE" and tx.get("contractName") == expected_contract_name:
return str(tx.get("contractAddress") or "").strip()
return ""
def query_token_meta(rpc_url: str, token: str) -> dict:
decimals = parse_uint(cast_call(rpc_url, token, "decimals()(uint8)"))
symbol = cast_call(rpc_url, token, "symbol()(string)")
return {"address": token, "symbol": symbol, "decimals": decimals}
def query_manager_state(rpc_url: str, manager: str) -> dict:
quote_token = parse_address(cast_call(rpc_url, manager, "quoteToken()(address)"))
receiver = parse_address(cast_call(rpc_url, manager, "receiver()(address)"))
state = {
"manager": manager,
"quoteToken": query_token_meta(rpc_url, quote_token),
"receiver": receiver,
"receiverOwner": parse_address(cast_call(rpc_url, manager, "receiverOwner()(address)")),
"isReceiverOwnedByManager": "true" in cast_call(rpc_url, manager, "isReceiverOwnedByManager()(bool)").lower(),
"quoteBalanceRaw": str(parse_uint(cast_call(rpc_url, manager, "quoteBalance()(uint256)"))),
"availableQuoteRaw": str(parse_uint(cast_call(rpc_url, manager, "availableQuote()(uint256)"))),
"receiverSweepableQuoteRaw": str(parse_uint(cast_call(rpc_url, manager, "receiverSweepableQuote()(uint256)"))),
"receiverReserveRetainedRaw": str(parse_uint(cast_call(rpc_url, manager, "receiverReserveRetained()(uint256)"))),
"managerReserveRetainedRaw": str(parse_uint(cast_call(rpc_url, manager, "managerReserveRetained()(uint256)"))),
"gasRecipient": parse_address(cast_call(rpc_url, manager, "gasRecipient()(address)")),
"recycleRecipient": parse_address(cast_call(rpc_url, manager, "recycleRecipient()(address)")),
}
decimals = state["quoteToken"]["decimals"]
state["quoteBalanceUnits"] = str(normalize_units(int(state["quoteBalanceRaw"]), decimals))
state["availableQuoteUnits"] = str(normalize_units(int(state["availableQuoteRaw"]), decimals))
state["receiverSweepableQuoteUnits"] = str(normalize_units(int(state["receiverSweepableQuoteRaw"]), decimals))
state["receiverReserveRetainedUnits"] = str(normalize_units(int(state["receiverReserveRetainedRaw"]), decimals))
state["managerReserveRetainedUnits"] = str(normalize_units(int(state["managerReserveRetainedRaw"]), decimals))
return state
def query_receiver_state(rpc_url: str, receiver: str, quote_token: str) -> dict:
return {
"receiver": receiver,
"owner": parse_address(cast_call(rpc_url, receiver, "owner()(address)")),
"quoteBalanceRaw": str(parse_uint(cast_call(rpc_url, quote_token, "balanceOf(address)(uint256)", receiver))),
}
def query_defended_quotes(rpc_url: str, defended_pool: str, trader: str, policy: dict) -> list[dict]:
rows: list[dict] = []
for item in policy["managedCycle"]["quoteAmountByDeviationBps"]:
amount_raw = int(item["flashQuoteAmountRaw"])
base_out_raw, mt_fee_raw = parse_uints(
cast_call(rpc_url, defended_pool, "querySellQuote(address,uint256)(uint256,uint256)", trader, str(amount_raw)),
2,
)
rows.append(
{
"minDeviationBps": int(item["minDeviationBps"]),
"flashQuoteAmountRaw": amount_raw,
"receiveBaseAmountRaw": str(base_out_raw),
"mtFeeRaw": str(mt_fee_raw),
}
)
return rows
def build_summary(snapshot: dict) -> dict:
public_health = snapshot["health"]["publicPairHealth"]
defended_health = snapshot["health"]["defendedVenueHealth"]
treasury = snapshot.get("treasuryManager") or {}
return {
"publicPairDeviationBps": public_health.get("deviationBps"),
"publicPairBaseReserveUnits": public_health.get("baseReserveUnits"),
"publicPairQuoteReserveUnits": public_health.get("quoteReserveUnits"),
"defendedMidPrice": defended_health.get("midPrice"),
"defendedDeviationBps": defended_health.get("deviationBps"),
"defendedBaseReserveRaw": defended_health.get("baseReserveRaw"),
"defendedQuoteReserveRaw": defended_health.get("quoteReserveRaw"),
"managerAvailableQuoteUnits": treasury.get("availableQuoteUnits"),
"receiverSweepableQuoteUnits": treasury.get("receiverSweepableQuoteUnits"),
"decisionAction": snapshot["health"]["decision"]["action"],
"decisionSeverity": snapshot["health"]["decision"]["severity"],
"flashQuoteAmountRaw": snapshot["health"]["decision"]["flashQuoteAmountRaw"],
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--out", help="Write the JSON snapshot to this file.")
args = parser.parse_args()
env_values = merged_env_values()
policy = load_json(POLICY_PATH)
health = run_health_checker()
rpc_url = ""
for key in policy["network"].get("rpcEnvKeys", []):
rpc_url = resolve_env_value(key, env_values)
if rpc_url:
break
if not rpc_url:
raise RuntimeError("missing mainnet RPC URL")
manager_addr = resolve_env_value("QUOTE_PUSH_TREASURY_MANAGER_MAINNET", env_values)
receiver_addr = resolve_env_value("AAVE_QUOTE_PUSH_RECEIVER_MAINNET", env_values)
if not receiver_addr:
receiver_addr = read_latest_create_address(BROADCAST_RECEIVER, "AaveQuotePushFlashReceiver")
if not manager_addr:
manager_addr = read_latest_create_address(BROADCAST_MANAGER, "QuotePushTreasuryManager")
defended_pool = health["defendedVenue"]["poolAddress"]
treasury_manager = None
receiver_state = None
defended_quotes = []
warnings: list[str] = []
if manager_addr and manager_addr.lower() != ZERO_ADDRESS:
try:
treasury_manager = query_manager_state(rpc_url, manager_addr)
receiver_addr = treasury_manager["receiver"]
except Exception as exc:
warnings.append(f"treasury manager query failed: {exc}")
else:
warnings.append("treasury manager query skipped: QUOTE_PUSH_TREASURY_MANAGER_MAINNET not configured")
if receiver_addr and receiver_addr.lower() != ZERO_ADDRESS:
quote_token = treasury_manager["quoteToken"]["address"] if treasury_manager else health["publicPair"]["quoteAddress"]
try:
receiver_state = query_receiver_state(rpc_url, receiver_addr, quote_token)
quote_decimals = treasury_manager["quoteToken"]["decimals"] if treasury_manager else 6
receiver_state["quoteBalanceUnits"] = str(normalize_units(int(receiver_state["quoteBalanceRaw"]), quote_decimals))
except Exception as exc:
warnings.append(f"receiver query failed: {exc}")
else:
warnings.append("receiver query skipped: AAVE_QUOTE_PUSH_RECEIVER_MAINNET not configured")
trader = receiver_addr if receiver_addr and receiver_addr.lower() != ZERO_ADDRESS else ""
if trader:
try:
defended_quotes = query_defended_quotes(rpc_url, defended_pool, trader, policy)
except Exception as exc:
warnings.append(f"defended quote query failed: {exc}")
else:
warnings.append("defended quote query skipped: no receiver configured")
snapshot = {
"generatedAt": datetime.now(timezone.utc).isoformat(),
"mode": "read_only_preflight",
"policyPath": str(POLICY_PATH),
"checkerPath": str(CHECKER_PATH),
"resolvedAddresses": {
"receiver": receiver_addr or None,
"treasuryManager": manager_addr or None,
},
"health": health,
"treasuryManager": treasury_manager,
"receiver": receiver_state,
"defendedLaneQuotes": defended_quotes,
"warnings": warnings,
}
snapshot["summary"] = build_summary(snapshot)
output = json.dumps(snapshot, indent=2)
if args.out:
out_path = Path(args.out)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(output + "\n")
print(output)
return 0
if __name__ == "__main__":
sys.exit(main())