#!/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()