Files
proxmox/scripts/verify/build-cw-public-repeg-plan.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

764 lines
30 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import json
import re
import subprocess
import time
from decimal import Decimal, InvalidOperation, getcontext
from pathlib import Path
getcontext().prec = 50
ROOT = Path(__file__).resolve().parents[2]
PRICE_REPORT = ROOT / "reports" / "status" / "cw-public-prices-latest.json"
DEPLOYMENT_STATUS = ROOT / "cross-chain-pmm-lps" / "config" / "deployment-status.json"
UNISWAP_DISCOVERY = ROOT / "reports" / "extraction" / "promod-uniswap-v2-live-pair-discovery-latest.json"
ROOT_ENV_PATH = ROOT / ".env"
SMOM_ENV_PATH = ROOT / "smom-dbis-138" / ".env"
JSON_OUT = ROOT / "reports" / "status" / "cw-public-repeg-plan-latest.json"
DOC_OUT = ROOT / "docs" / "03-deployment" / "CW_PUBLIC_NETWORK_REPEG_PLAN.md"
ADDRESS_RE = re.compile(r"0x[a-fA-F0-9]{40}")
UINT_RE = re.compile(r"\b\d+\b")
TARGETS = {
"cWUSDC": Decimal("1"),
"cWUSDT": Decimal("1"),
"cWAUSDT": Decimal("1"),
"cWUSDW": Decimal("1"),
"cWEURC": Decimal("1.08"),
"cWEURT": Decimal("1.08"),
"cWGBPC": Decimal("1.27"),
"cWGBPT": Decimal("1.27"),
"cWAUDC": Decimal("0.66"),
"cWJPYC": Decimal("0.0067"),
"cWCHFC": Decimal("1.11"),
"cWCADC": Decimal("0.74"),
"cWXAUC": Decimal("3200"),
"cWXAUT": Decimal("3200"),
}
DODO_THRESHOLD_PCT = Decimal("1")
UNISWAP_THRESHOLD_PCT = Decimal("1")
DODO_ENV_KEYS = {
1: ["DODO_PMM_INTEGRATION_MAINNET"],
10: ["DODO_PMM_INTEGRATION_OPTIMISM"],
25: ["DODO_PMM_INTEGRATION_CRONOS"],
56: ["DODO_PMM_INTEGRATION_BSC"],
100: ["DODO_PMM_INTEGRATION_GNOSIS"],
137: ["DODO_PMM_INTEGRATION_POLYGON"],
42220: ["DODO_PMM_INTEGRATION_CELO"],
43114: ["DODO_PMM_INTEGRATION_AVALANCHE"],
8453: ["DODO_PMM_INTEGRATION_BASE"],
42161: ["DODO_PMM_INTEGRATION_ARBITRUM"],
}
RPC_ENV_KEYS = {
1: ["ETHEREUM_MAINNET_RPC"],
10: ["OPTIMISM_RPC_URL", "OPTIMISM_MAINNET_RPC"],
25: ["CRONOS_RPC_URL", "CRONOS_MAINNET_RPC"],
56: ["BSC_RPC_URL", "BSC_MAINNET_RPC"],
100: ["GNOSIS_RPC_URL", "GNOSIS_MAINNET_RPC", "GNOSIS_RPC"],
137: ["POLYGON_MAINNET_RPC", "POLYGON_RPC_URL"],
42220: ["CELO_RPC_URL", "CELO_MAINNET_RPC", "CELO_RPC"],
43114: ["AVALANCHE_RPC_URL", "AVALANCHE_MAINNET_RPC"],
8453: ["BASE_RPC_URL", "BASE_MAINNET_RPC"],
42161: ["ARBITRUM_RPC_URL", "ARBITRUM_MAINNET_RPC"],
}
def now() -> str:
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
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))
values.update(load_env_from_shell())
return values
def load_env_from_shell() -> dict[str, str]:
loader = ROOT / "smom-dbis-138" / "scripts" / "load-env.sh"
if not loader.exists():
return {}
proc = subprocess.run(
[
"bash",
"-lc",
f"source {loader} >/dev/null 2>&1 && env",
],
text=True,
capture_output=True,
timeout=15,
check=False,
cwd=ROOT,
)
if proc.returncode != 0:
return {}
values: dict[str, str] = {}
for raw_line in proc.stdout.splitlines():
if "=" not in raw_line:
continue
key, value = raw_line.split("=", 1)
values[key.strip()] = value.strip()
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 = 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]
proc = subprocess.run(cmd, text=True, capture_output=True, timeout=8, check=False)
if proc.returncode != 0:
stderr = proc.stderr.strip() or proc.stdout.strip() or "cast call failed"
raise RuntimeError(stderr)
return proc.stdout.strip()
def parse_uint(value: str) -> int:
cleaned = re.sub(r"\[[^\]]*\]", "", value)
matches = UINT_RE.findall(cleaned)
if matches:
return int(matches[0])
for line in value.splitlines():
token = line.strip().split(" ", 1)[0]
if token.isdigit():
return int(token)
raise ValueError(f"could not parse integer from {value!r}")
def parse_uints(value: str, count: int) -> list[int]:
cleaned = re.sub(r"\[[^\]]*\]", "", value)
matches = [int(match) for match in UINT_RE.findall(cleaned)]
if len(matches) >= count:
return matches[:count]
matches = []
for line in value.splitlines():
token = line.strip().split(" ", 1)[0]
if token.isdigit():
matches.append(int(token))
if len(matches) < count:
raise ValueError(f"expected {count} integers from {value!r}")
return matches[:count]
def normalize_units(raw: int, decimals: int) -> Decimal:
return Decimal(raw) / (Decimal(10) ** decimals)
def write_json(path: Path, payload: dict) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(payload, indent=2) + "\n")
def write_text(path: Path, text: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text.rstrip() + "\n")
def safe_decimal(value: str | None) -> Decimal | None:
if value is None:
return None
try:
return Decimal(value)
except (InvalidOperation, ValueError):
return None
def pct_deviation(current: Decimal, target: Decimal) -> Decimal:
return ((current - target) / target) * Decimal("100")
def format_decimal(value: Decimal | None, places: int = 8) -> str:
if value is None:
return "not found"
quant = Decimal(10) ** -places
try:
value = value.quantize(quant)
except InvalidOperation:
pass
return format(value, "f")
def format_pct(value: Decimal) -> str:
sign = "+" if value >= 0 else ""
return f"{sign}{format_decimal(value, 2)}%"
def first_address(texts: list[str]) -> str | None:
for text in texts:
match = ADDRESS_RE.search(text)
if match:
return match.group(0)
return None
def command_block(lines: list[str]) -> str:
return "\n".join(lines)
def derive_deployer(env_values: dict[str, str]) -> str:
pk = resolve_env_value("PRIVATE_KEY", env_values) or resolve_env_value("KEEPER_PRIVATE_KEY", env_values)
if not pk or "${" in pk:
return ""
proc = subprocess.run(
["cast", "wallet", "address", "--private-key", pk],
text=True,
capture_output=True,
timeout=8,
check=False,
)
if proc.returncode != 0:
return ""
match = ADDRESS_RE.search(proc.stdout.strip())
return match.group(0) if match else ""
def build_pair_to_pool(chain: dict) -> dict[str, list[dict]]:
pairs: dict[str, list[dict]] = {}
for row in chain.get("pmmPools") or []:
pairs.setdefault(f"{row['base']}/{row['quote']}", []).append(row)
for row in chain.get("uniswapV2Pools") or []:
pairs.setdefault(f"{row['base']}/{row['quote']}", []).append(row)
return pairs
def select_pool(pair_rows: list[dict], source_type: str) -> dict:
if not pair_rows:
return {}
if source_type == "dodo_pmm":
for row in pair_rows:
if row.get("venue") == "dodo_pmm" or row.get("poolType") == "stable_quote" or "k" in row:
return row
if source_type == "uniswap_v2":
for row in pair_rows:
if row.get("venue") == "uniswap_v2_pair":
return row
return pair_rows[0]
def dodo_action(pair: str, current: Decimal, target: Decimal) -> str:
if current < target:
return f"Fund quote side and buy base through `{pair}` until `getMidPrice()` returns target."
return f"Fund base side and sell base into `{pair}` until `getMidPrice()` returns target."
def uniswap_action(pair: str, target: Decimal) -> str:
return (
f"Withdraw or ignore bad LP, then reseed `{pair}` through the chain router at target ratio `{target}` "
"with balanced reserves."
)
def integration_for_chain(chain_id: int, env_values: dict[str, str]) -> str:
for key in DODO_ENV_KEYS.get(chain_id, []):
value = resolve_env_value(key, env_values)
if value:
return value
return ""
def rpc_for_chain(chain_id: int, env_values: dict[str, str]) -> str:
if chain_id == 1:
infura_project_id = resolve_env_value("INFURA_PROJECT_ID", env_values)
if infura_project_id:
return f"https://mainnet.infura.io/v3/{infura_project_id}"
for key in RPC_ENV_KEYS.get(chain_id, []):
value = resolve_env_value(key, env_values)
if value:
return value
return ""
def rpc_var_for_chain(chain_id: int) -> str:
return RPC_ENV_KEYS.get(chain_id, ["RPC_URL"])[0]
def dodo_commands(chain_id: int, pair: str, pool_address: str, current: Decimal, target: Decimal, chain_info: dict, env_values: dict[str, str]) -> dict:
base_symbol, quote_symbol = pair.split("/")
integration = integration_for_chain(chain_id, env_values)
rpc_var = rpc_var_for_chain(chain_id)
base_address = (chain_info.get("cwTokens") or {}).get(base_symbol) or (chain_info.get("anchorAddresses") or {}).get(base_symbol) or "REPLACE_BASE_TOKEN"
quote_address = (chain_info.get("cwTokens") or {}).get(quote_symbol) or (chain_info.get("anchorAddresses") or {}).get(quote_symbol) or "REPLACE_QUOTE_TOKEN"
if current < target:
return {
"direction": "quote_in_buy_base",
"commands": command_block(
[
"source smom-dbis-138/scripts/load-env.sh >/dev/null",
f"export RPC_URL=\"${{{rpc_var}}}\"",
f"export INTEGRATION=\"{integration or 'REPLACE_DODO_INTEGRATION'}\"",
f"export POOL=\"{pool_address or 'REPLACE_POOL'}\"",
f"export BASE_TOKEN=\"{base_address}\"",
f"export QUOTE_TOKEN=\"{quote_address}\"",
"export QUOTE_IN_RAW=REPLACE_QUOTE_IN_RAW",
"export MIN_BASE_OUT_RAW=REPLACE_MIN_BASE_OUT_RAW",
'cast send "$QUOTE_TOKEN" \'approve(address,uint256)(bool)\' "$INTEGRATION" "$QUOTE_IN_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
'cast send "$INTEGRATION" \'swapExactIn(address,address,uint256,uint256)\' "$POOL" "$QUOTE_TOKEN" "$QUOTE_IN_RAW" "$MIN_BASE_OUT_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
]
),
}
return {
"direction": "base_in_sell_base",
"commands": command_block(
[
"source smom-dbis-138/scripts/load-env.sh >/dev/null",
f"export RPC_URL=\"${{{rpc_var}}}\"",
f"export INTEGRATION=\"{integration or 'REPLACE_DODO_INTEGRATION'}\"",
f"export POOL=\"{pool_address or 'REPLACE_POOL'}\"",
f"export BASE_TOKEN=\"{base_address}\"",
f"export QUOTE_TOKEN=\"{quote_address}\"",
"export BASE_IN_RAW=REPLACE_BASE_IN_RAW",
"export MIN_QUOTE_OUT_RAW=REPLACE_MIN_QUOTE_OUT_RAW",
'cast send "$BASE_TOKEN" \'approve(address,uint256)(bool)\' "$INTEGRATION" "$BASE_IN_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
'cast send "$INTEGRATION" \'swapExactIn(address,address,uint256,uint256)\' "$POOL" "$BASE_TOKEN" "$BASE_IN_RAW" "$MIN_QUOTE_OUT_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
]
),
}
def uniswap_commands(chain_id: int, pair: str, pool_address: str, chain_info: dict) -> dict:
token_a, token_b = pair.split("/")
rpc_var = rpc_var_for_chain(chain_id)
router = ""
for row in chain_info.get("uniswapV2Pools") or []:
if f"{row['base']}/{row['quote']}" == pair and row.get("routerAddress"):
router = row["routerAddress"]
break
token_a_address = (chain_info.get("cwTokens") or {}).get(token_a) or (chain_info.get("anchorAddresses") or {}).get(token_a) or "REPLACE_TOKEN_A"
token_b_address = (chain_info.get("cwTokens") or {}).get(token_b) or (chain_info.get("anchorAddresses") or {}).get(token_b) or "REPLACE_TOKEN_B"
return {
"commands": command_block(
[
"source smom-dbis-138/scripts/load-env.sh >/dev/null",
f"export RPC_URL=\"${{{rpc_var}}}\"",
f"export ROUTER=\"{router or f'${{CHAIN_{chain_id}_UNISWAP_V2_ROUTER}}'}\"",
f"export PAIR=\"{pool_address}\"",
f"export TOKEN_A=\"{token_a_address}\"",
f"export TOKEN_B=\"{token_b_address}\"",
"export AMOUNT_A_RAW=REPLACE_AMOUNT_A_RAW",
"export AMOUNT_B_RAW=REPLACE_AMOUNT_B_RAW",
'export DEADLINE="$(( $(date +%s) + 3600 ))"',
'export SIGNER="$(cast wallet address --private-key "$PRIVATE_KEY")"',
'# Optional: remove bad LP first if you control LP tokens for this pair.',
'cast send "$TOKEN_A" \'approve(address,uint256)(bool)\' "$ROUTER" "$AMOUNT_A_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
'cast send "$TOKEN_B" \'approve(address,uint256)(bool)\' "$ROUTER" "$AMOUNT_B_RAW" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
'cast send "$ROUTER" \'addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256)\' \\',
' "$TOKEN_A" "$TOKEN_B" "$AMOUNT_A_RAW" "$AMOUNT_B_RAW" "$AMOUNT_A_RAW" "$AMOUNT_B_RAW" "$SIGNER" "$DEADLINE" \\',
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
]
),
}
def dodo_sizing_and_balance(
chain_id: int,
pair: str,
pool_address: str,
current: Decimal,
target: Decimal,
chain_info: dict,
env_values: dict[str, str],
deployer: str,
) -> dict:
rpc_url = rpc_for_chain(chain_id, env_values)
base_symbol, quote_symbol = pair.split("/")
base_address = (chain_info.get("cwTokens") or {}).get(base_symbol) or (chain_info.get("anchorAddresses") or {}).get(base_symbol) or ""
quote_address = (chain_info.get("cwTokens") or {}).get(quote_symbol) or (chain_info.get("anchorAddresses") or {}).get(quote_symbol) or ""
result = {
"heuristic": "suggested_raw = simple reserve-parity top-up on the funding side using target quote-per-base",
"deployer": deployer or None,
"rpcConfigured": bool(rpc_url),
}
if not rpc_url or not base_address or not quote_address or not pool_address:
result["error"] = "missing rpc or token/pool address"
return result
try:
base_decimals = parse_uint(cast_call(rpc_url, base_address, "decimals()(uint8)"))
quote_decimals = parse_uint(cast_call(rpc_url, quote_address, "decimals()(uint8)"))
base_reserve_raw, quote_reserve_raw = parse_uints(
cast_call(rpc_url, pool_address, "getVaultReserve()(uint256,uint256)"), 2
)
except Exception as exc:
result["error"] = str(exc)
return result
gap_fraction = abs(target - current) / target
base_units = normalize_units(base_reserve_raw, base_decimals)
quote_units = normalize_units(quote_reserve_raw, quote_decimals)
if current < target:
funding_symbol = quote_symbol
funding_address = quote_address
funding_decimals = quote_decimals
target_quote_units = base_units * target
top_up_units = max(target_quote_units - quote_units, Decimal(0))
suggested_raw = int((top_up_units * (Decimal(10) ** quote_decimals)).to_integral_value())
else:
funding_symbol = base_symbol
funding_address = base_address
funding_decimals = base_decimals
target_base_units = quote_units / target
top_up_units = max(target_base_units - base_units, Decimal(0))
suggested_raw = int((top_up_units * (Decimal(10) ** base_decimals)).to_integral_value())
deployer_balance_raw = None
if deployer:
try:
deployer_balance_raw = parse_uint(cast_call(rpc_url, funding_address, "balanceOf(address)(uint256)", deployer))
except Exception as exc:
result["deployerBalanceError"] = str(exc)
result.update(
{
"baseToken": {"symbol": base_symbol, "address": base_address, "decimals": base_decimals},
"quoteToken": {"symbol": quote_symbol, "address": quote_address, "decimals": quote_decimals},
"poolReserves": {
"baseRaw": str(base_reserve_raw),
"baseUnits": str(normalize_units(base_reserve_raw, base_decimals)),
"quoteRaw": str(quote_reserve_raw),
"quoteUnits": str(normalize_units(quote_reserve_raw, quote_decimals)),
},
"gapFraction": str(gap_fraction),
"fundingSide": funding_symbol,
"suggestedTradeRaw": str(suggested_raw),
"suggestedTradeUnits": str(normalize_units(suggested_raw, funding_decimals)),
}
)
if deployer_balance_raw is not None:
shortfall = max(suggested_raw - deployer_balance_raw, 0)
result["deployerFundingCheck"] = {
"token": funding_symbol,
"balanceRaw": str(deployer_balance_raw),
"balanceUnits": str(normalize_units(deployer_balance_raw, funding_decimals)),
"shortfallRaw": str(shortfall),
"shortfallUnits": str(normalize_units(shortfall, funding_decimals)),
"covered": shortfall == 0,
}
return result
def live_uniswap_ratio(
chain_id: int,
pair_address: str,
base_symbol: str,
quote_symbol: str,
chain_info: dict,
env_values: dict[str, str],
) -> Decimal | None:
rpc_url = rpc_for_chain(chain_id, env_values)
if not rpc_url or not pair_address:
return None
base_address = ((chain_info.get("cwTokens") or {}).get(base_symbol) or (chain_info.get("anchorAddresses") or {}).get(base_symbol) or "").lower()
quote_address = ((chain_info.get("cwTokens") or {}).get(quote_symbol) or (chain_info.get("anchorAddresses") or {}).get(quote_symbol) or "").lower()
if not base_address or not quote_address:
return None
try:
token0 = cast_call(rpc_url, pair_address, "token0()(address)").strip().lower()
token1 = cast_call(rpc_url, pair_address, "token1()(address)").strip().lower()
reserve0_raw, reserve1_raw, _ = parse_uints(cast_call(rpc_url, pair_address, "getReserves()((uint112,uint112,uint32))"), 3)
decimals0 = parse_uint(cast_call(rpc_url, token0, "decimals()(uint8)"))
decimals1 = parse_uint(cast_call(rpc_url, token1, "decimals()(uint8)"))
except Exception:
return None
reserve_by_token = {
token0: normalize_units(reserve0_raw, decimals0),
token1: normalize_units(reserve1_raw, decimals1),
}
base_units = reserve_by_token.get(base_address)
quote_units = reserve_by_token.get(quote_address)
if base_units in (None, Decimal(0)) or quote_units is None:
return None
return quote_units / base_units
def build_payload() -> dict:
env_values = merged_env_values()
deployer = derive_deployer(env_values)
prices = load_json(PRICE_REPORT)
deployment = load_json(DEPLOYMENT_STATUS)
discovery = load_json(UNISWAP_DISCOVERY)
dodo_findings: list[dict] = []
uniswap_findings: list[dict] = []
unpriced: list[dict] = []
for chain in prices.get("chains") or []:
chain_id = str(chain["chainId"])
chain_info = deployment["chains"].get(chain_id, {})
pair_map = build_pair_to_pool(chain_info)
for symbol, row in sorted(chain.get("prices", {}).items()):
target = TARGETS.get(symbol)
current = safe_decimal(row.get("priceUsd"))
if current is None:
if target is not None:
unpriced.append(
{
"chainId": chain["chainId"],
"network": chain["network"],
"token": symbol,
"targetUsd": str(target),
"reason": "no live price path found from current public snapshot",
}
)
continue
if target is None:
continue
deviation = pct_deviation(current, target)
if abs(deviation) <= DODO_THRESHOLD_PCT:
continue
derived_from = row["derivedFrom"]
if " -> " in derived_from:
# Derived route; fix the direct broken pool(s) below in the Uniswap section.
continue
pool = select_pool(pair_map.get(derived_from, []), row["sourceType"])
pool_address = pool.get("poolAddress") or first_address(row.get("notes", []))
dodo_findings.append(
{
"chainId": chain["chainId"],
"network": chain["network"],
"token": symbol,
"pair": derived_from,
"poolAddress": pool_address,
"venue": row["sourceType"],
"currentUsd": str(current),
"targetUsd": str(target),
"deviationPct": str(deviation),
"action": dodo_action(derived_from, current, target),
"operator": dodo_commands(chain["chainId"], derived_from, pool_address or "", current, target, chain_info, env_values),
"sizing": dodo_sizing_and_balance(chain["chainId"], derived_from, pool_address or "", current, target, chain_info, env_values, deployer),
}
)
for entry in discovery.get("entries") or []:
chain_info = deployment["chains"].get(str(entry["chain_id"]), {})
for row in entry.get("pairsChecked") or []:
if not row.get("live"):
continue
pair = f"{row['base']}/{row['quote']}"
target = Decimal("1")
current = live_uniswap_ratio(entry["chain_id"], row["poolAddress"], row["base"], row["quote"], chain_info, env_values)
if current is None:
current = safe_decimal((row.get("health") or {}).get("priceQuotePerBase"))
if current is None:
continue
deviation = pct_deviation(current, target)
if abs(deviation) <= UNISWAP_THRESHOLD_PCT:
continue
if pair not in ("cWUSDT/cWUSDC", "cWAUSDT/cWUSDT", "cWAUSDT/cWUSDC"):
continue
uniswap_findings.append(
{
"chainId": entry["chain_id"],
"network": entry["network"],
"pair": pair,
"poolAddress": row["poolAddress"],
"currentRatio": str(current),
"targetRatio": str(target),
"deviationPct": str(deviation),
"healthy": (row.get("health") or {}).get("healthy"),
"action": uniswap_action(pair, target),
"operator": uniswap_commands(entry["chain_id"], pair, row["poolAddress"], chain_info),
}
)
dodo_findings.sort(key=lambda row: (row["chainId"], row["pair"]))
uniswap_findings.sort(key=lambda row: (row["chainId"], row["pair"]))
unpriced.sort(key=lambda row: (row["chainId"], row["token"]))
return {
"generatedAt": now(),
"inputs": {
"priceReport": str(PRICE_REPORT),
"deploymentStatus": str(DEPLOYMENT_STATUS),
"uniswapDiscovery": str(UNISWAP_DISCOVERY),
},
"targetsUsd": {k: str(v) for k, v in TARGETS.items()},
"thresholds": {
"dodoDeviationPct": str(DODO_THRESHOLD_PCT),
"uniswapDeviationPct": str(UNISWAP_THRESHOLD_PCT),
},
"deployer": deployer or None,
"offPegDodoPools": dodo_findings,
"offPegUniswapPairs": uniswap_findings,
"unpricedTargets": unpriced,
}
def render_markdown(payload: dict) -> str:
lines = [
"# cW Public Network Repeg Plan",
"",
f"- Generated: `{payload['generatedAt']}`",
f"- Price report: `{payload['inputs']['priceReport']}`",
f"- Deployment inventory: `{payload['inputs']['deploymentStatus']}`",
f"- Uniswap discovery: `{payload['inputs']['uniswapDiscovery']}`",
"- Scope: current off-peg or unreadable public-network `cW*` pools only.",
"- PMM rule: if current price is below target, fund quote and buy base; if current price is above target, fund base and sell base.",
"- Uniswap rule: remove bad LP or ignore stale LP, then reseed at the target reserve ratio.",
"",
"## Off-Peg DODO PMM Pools",
"",
"| Chain | Pair | Pool | Current | Target | Deviation | Repair Path |",
"|---|---|---|---:|---:|---:|---|",
]
if payload["offPegDodoPools"]:
for row in payload["offPegDodoPools"]:
lines.append(
f"| `{row['chainId']}` {row['network']} | `{row['pair']}` | `{row['poolAddress'] or 'unknown'}` | "
f"`{format_decimal(safe_decimal(row['currentUsd']))}` | `{format_decimal(safe_decimal(row['targetUsd']))}` | "
f"`{format_pct(Decimal(row['deviationPct']))}` | {row['action']} |"
)
else:
lines.append("| — | — | — | — | — | — | No off-peg DODO PMM pools found at the configured threshold. |")
lines.extend(
[
"",
"## Broken Uniswap Pairs",
"",
"| Chain | Pair | Pool | Current Ratio | Target | Deviation | Repair Path |",
"|---|---|---|---:|---:|---:|---|",
]
)
if payload["offPegUniswapPairs"]:
for row in payload["offPegUniswapPairs"]:
lines.append(
f"| `{row['chainId']}` {row['network']} | `{row['pair']}` | `{row['poolAddress']}` | "
f"`{format_decimal(safe_decimal(row['currentRatio']))}` | `{format_decimal(safe_decimal(row['targetRatio']))}` | "
f"`{format_pct(Decimal(row['deviationPct']))}` | {row['action']} |"
)
else:
lines.append("| — | — | — | — | — | — | No broken Uniswap pairs found at the configured threshold. |")
lines.extend(
[
"",
"## Unpriced Targets",
"",
"| Chain | Token | Target | Status |",
"|---|---|---:|---|",
]
)
if payload["unpricedTargets"]:
for row in payload["unpricedTargets"]:
lines.append(
f"| `{row['chainId']}` {row['network']} | `{row['token']}` | "
f"`{format_decimal(safe_decimal(row['targetUsd']))}` | {row['reason']} |"
)
else:
lines.append("| — | — | — | No unpriced targets. |")
lines.extend(
[
"",
"## Execution Order",
"",
"1. Repeg direct PMM anchor pools first: `cWUSDC/USDC`, `cWUSDT/USDT`, then the fiat/metal quoted rails.",
"2. Repeg `cWUSDT/cWUSDC` next on any chain where the wrapped support pair is broken.",
"3. Repeg wrapped edge pairs such as `cWAUSDT/cWUSDT` and `cWAUSDT/cWUSDC` after the core wrapped support rail is healthy.",
"4. Re-run the price table and this repeg plan after each venue is repaired.",
"",
f"- Deployer inspected: `{payload.get('deployer') or 'not found in env'}`",
"",
"## Operator Commands",
"",
]
)
for row in payload["offPegDodoPools"]:
sizing = row.get("sizing") or {}
funding = sizing.get("deployerFundingCheck") or {}
reserve_note = ""
pool_reserves = sizing.get("poolReserves") or {}
if sizing.get("error"):
reserve_note = f"- Sizing note: `{sizing['error']}`"
elif pool_reserves.get("baseRaw") == "0" and pool_reserves.get("quoteRaw") == "0":
reserve_note = "- Sizing note: `Pool reports zero vault reserves; heuristic trade size is informational only.`"
lines.extend(
[
f"### `{row['chainId']}` {row['network']} `{row['pair']}`",
"",
f"- Suggested funding side: `{sizing.get('fundingSide', 'unknown')}`",
f"- Suggested trade raw: `{sizing.get('suggestedTradeRaw', 'unknown')}`",
f"- Suggested trade units: `{sizing.get('suggestedTradeUnits', 'unknown')}`",
f"- Gap fraction: `{format_decimal(safe_decimal(sizing.get('gapFraction')), 6) if sizing.get('gapFraction') else 'unknown'}`",
f"- Deployer balance on funding side: `{funding.get('balanceUnits', 'unknown')}` `{funding.get('token', '')}`",
f"- Deployer shortfall: `{funding.get('shortfallUnits', 'unknown')}` `{funding.get('token', '')}`",
f"- Covered: `{funding.get('covered', 'unknown')}`",
*(["- Reserve snapshot: `baseRaw=0 quoteRaw=0`"] if reserve_note and "zero vault reserves" in reserve_note else []),
*([reserve_note] if reserve_note else []),
"",
"```bash",
row["operator"]["commands"],
"```",
"",
]
)
for row in payload["offPegUniswapPairs"]:
lines.extend(
[
f"### `{row['chainId']}` {row['network']} `{row['pair']}`",
"",
"```bash",
row["operator"]["commands"],
"```",
"",
]
)
return "\n".join(lines)
def main() -> None:
payload = build_payload()
write_json(JSON_OUT, payload)
write_text(DOC_OUT, render_markdown(payload))
print(JSON_OUT)
print(DOC_OUT)
if __name__ == "__main__":
main()