All checks were successful
Deploy to Phoenix / validate (push) Successful in 1m16s
Deploy to Phoenix / deploy (push) Successful in 44s
Deploy to Phoenix / deploy-atomic-swap-dapp (push) Successful in 1m28s
phoenix-deploy Deployed to cloudflare-sync
Deploy to Phoenix / cloudflare (push) Successful in 39s
551 lines
26 KiB
Python
Executable File
551 lines
26 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Plan DBIS Engine X cWUSDC recipient deposits.
|
|
|
|
Read-only planner for the 138 cUSDC -> Mainnet cWUSDC -> Engine X virtual-batch
|
|
recipient deposit path. It intentionally emits dry-run/review commands only.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import math
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timezone
|
|
from decimal import Decimal, getcontext
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
getcontext().prec = 80
|
|
|
|
DEFAULT_RECIPIENTS = [
|
|
("meta", "0x148ca6efce22829d12f17da9b6e169689d6bb8ac"),
|
|
("master", "0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e"),
|
|
]
|
|
|
|
MAINNET_SELECTOR = 5009297550715157269
|
|
DEPLOYER_FALLBACK = "0x4A666F96fC8764181194447A7dFdb7d471b301C8"
|
|
CHAIN138_CUSDC = "0xf22258f57794CC8E06237084b353Ab30fFfa640b"
|
|
MAINNET_CWUSDC = "0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a"
|
|
MAINNET_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
MAINNET_XAUT = "0x68749665FF8D2d112Fa859AA293F07A622782F38"
|
|
MAINTAINED_VAULT = "0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6"
|
|
DEBT_PER_LOOP_RAW = 5_000_000
|
|
XAUT_USD_PRICE6 = 3_226_640_000
|
|
LTV_BPS = 8_000
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
mode = parser.add_mutually_exclusive_group()
|
|
mode.add_argument(
|
|
"--per-recipient",
|
|
default="5000000000",
|
|
help="Human cWUSDC target per recipient. Default: 5,000,000,000 each.",
|
|
)
|
|
mode.add_argument(
|
|
"--total",
|
|
help="Human cWUSDC target split evenly across all recipients.",
|
|
)
|
|
parser.add_argument(
|
|
"--recipient",
|
|
action="append",
|
|
default=[],
|
|
help="Recipient as label:address. May be repeated. Defaults to meta and master wallets.",
|
|
)
|
|
parser.add_argument(
|
|
"--json-out",
|
|
default="reports/status/dbis-engine-x-recipient-deposit-plan-latest.json",
|
|
help="JSON output path.",
|
|
)
|
|
parser.add_argument(
|
|
"--md-out",
|
|
default="reports/status/dbis-engine-x-recipient-deposit-plan-latest.md",
|
|
help="Markdown output path.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def run(cmd: list[str], *, allow_fail: bool = False) -> str:
|
|
proc = subprocess.run(cmd, text=True, capture_output=True, check=False)
|
|
if proc.returncode != 0:
|
|
if allow_fail:
|
|
return proc.stderr.strip() or proc.stdout.strip()
|
|
raise RuntimeError(f"{' '.join(cmd)} failed: {proc.stderr.strip()}")
|
|
return proc.stdout.strip()
|
|
|
|
|
|
def first_uint(output: str) -> int | None:
|
|
match = re.search(r"\b(\d+)\b", output)
|
|
return int(match.group(1)) if match else None
|
|
|
|
|
|
def first_address(output: str) -> str | None:
|
|
match = re.search(r"0x[a-fA-F0-9]{40}", output)
|
|
return match.group(0) if match else None
|
|
|
|
|
|
def raw_from_human(value: str) -> int:
|
|
return int((Decimal(value.replace(",", "")) * Decimal(1_000_000)).to_integral_exact())
|
|
|
|
|
|
def human(raw: int, decimals: int = 6) -> str:
|
|
value = Decimal(raw) / (Decimal(10) ** decimals)
|
|
return f"{value:,.{decimals}f}"
|
|
|
|
|
|
def get_amount_in(amount_out: int, reserve_in: int, reserve_out: int) -> int:
|
|
if amount_out <= 0 or reserve_in <= 0 or reserve_out <= amount_out:
|
|
raise ValueError("insufficient liquidity")
|
|
numerator = reserve_in * amount_out * 1000
|
|
denominator = (reserve_out - amount_out) * 997
|
|
return numerator // denominator + 1
|
|
|
|
|
|
def get_amount_out(amount_in: int, reserve_in: int, reserve_out: int) -> int:
|
|
if amount_in <= 0 or reserve_in <= 0 or reserve_out <= 0:
|
|
raise ValueError("insufficient liquidity")
|
|
amount_in_with_fee = amount_in * 997
|
|
numerator = amount_in_with_fee * reserve_out
|
|
denominator = reserve_in * 1000 + amount_in_with_fee
|
|
return numerator // denominator
|
|
|
|
|
|
def min_xaut_collateral(debt_usdc: int) -> int:
|
|
numerator = debt_usdc * 1_000_000 * 10_000
|
|
denominator = XAUT_USD_PRICE6 * LTV_BPS
|
|
return (numerator + denominator - 1) // denominator
|
|
|
|
|
|
@dataclass
|
|
class RecipientPlan:
|
|
label: str
|
|
address: str
|
|
target_out_raw: int
|
|
loops: int
|
|
gross_in_raw: int
|
|
output_raw: int
|
|
preview_output_raw: int
|
|
rounding_raw: int
|
|
neutralized_raw: int
|
|
virtual_debt_raw: int
|
|
|
|
|
|
def parse_recipients(values: list[str]) -> list[tuple[str, str]]:
|
|
if not values:
|
|
return DEFAULT_RECIPIENTS
|
|
recipients: list[tuple[str, str]] = []
|
|
for item in values:
|
|
if ":" not in item:
|
|
raise SystemExit(f"recipient must be label:address: {item}")
|
|
label, address = item.split(":", 1)
|
|
if not re.fullmatch(r"0x[a-fA-F0-9]{40}", address):
|
|
raise SystemExit(f"invalid recipient address: {address}")
|
|
recipients.append((label, address))
|
|
return recipients
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
recipients = parse_recipients(args.recipient)
|
|
|
|
if args.total:
|
|
total_raw = raw_from_human(args.total)
|
|
target_per_recipient_raw = total_raw // len(recipients)
|
|
else:
|
|
target_per_recipient_raw = raw_from_human(args.per_recipient)
|
|
|
|
rpc138 = os.environ.get("RPC_URL_138") or os.environ.get("CHAIN138_RPC") or "http://192.168.11.211:8545"
|
|
rpc1 = os.environ.get("ETHEREUM_MAINNET_RPC") or os.environ.get("MAINNET_RPC_URL")
|
|
if not rpc1:
|
|
raise SystemExit("ETHEREUM_MAINNET_RPC or MAINNET_RPC_URL is required")
|
|
|
|
deployer = os.environ.get("DEPLOYER_ADDRESS") or DEPLOYER_FALLBACK
|
|
if os.environ.get("PRIVATE_KEY"):
|
|
deployer = run(["cast", "wallet", "address", "--private-key", os.environ["PRIVATE_KEY"]])
|
|
|
|
bridge = os.environ.get("CW_L1_BRIDGE_CHAIN138", "")
|
|
cusdc = os.environ.get("CUSDC_ADDRESS_138") or os.environ.get("COMPLIANT_USDC_ADDRESS") or CHAIN138_CUSDC
|
|
cwusdc = os.environ.get("CWUSDC_MAINNET") or MAINNET_CWUSDC
|
|
maintained_vault = os.environ.get("DBIS_ENGINE_X_MAINTAINED_VAULT") or MAINTAINED_VAULT
|
|
|
|
chain138_cusdc = first_uint(
|
|
run(["cast", "call", cusdc, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc138], allow_fail=True)
|
|
) or 0
|
|
mainnet_cwusdc = first_uint(
|
|
run(["cast", "call", cwusdc, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc1], allow_fail=True)
|
|
) or 0
|
|
mainnet_eth = first_uint(run(["cast", "balance", deployer, "--rpc-url", rpc1], allow_fail=True)) or 0
|
|
mainnet_gas_price = first_uint(run(["cast", "gas-price", "--rpc-url", rpc1], allow_fail=True)) or 0
|
|
|
|
pool_cw = first_uint(
|
|
run(["cast", "call", maintained_vault, "poolCwusdcReserve()(uint256)", "--rpc-url", rpc1], allow_fail=True)
|
|
) or 0
|
|
pool_usdc = first_uint(
|
|
run(["cast", "call", maintained_vault, "poolUsdcReserve()(uint256)", "--rpc-url", rpc1], allow_fail=True)
|
|
) or 0
|
|
lender = first_uint(
|
|
run(["cast", "call", maintained_vault, "lenderUsdcAvailable()(uint256)", "--rpc-url", rpc1], allow_fail=True)
|
|
) or 0
|
|
|
|
if pool_cw <= 0 or pool_usdc <= 0:
|
|
raise SystemExit("could not read maintained vault reserves")
|
|
|
|
cw_in_per_loop = get_amount_in(DEBT_PER_LOOP_RAW, pool_cw, pool_usdc)
|
|
cw_reserve_after_in = pool_cw + cw_in_per_loop
|
|
usdc_reserve_after_out = pool_usdc - DEBT_PER_LOOP_RAW
|
|
cw_out_per_loop = get_amount_out(DEBT_PER_LOOP_RAW, usdc_reserve_after_out, cw_reserve_after_in)
|
|
neutralized_per_loop = cw_in_per_loop - cw_out_per_loop
|
|
xaut_collateral = min_xaut_collateral(DEBT_PER_LOOP_RAW)
|
|
|
|
recipient_plans: list[RecipientPlan] = []
|
|
for label, address in recipients:
|
|
loops = math.ceil(target_per_recipient_raw / cw_out_per_loop)
|
|
recipient_plans.append(
|
|
RecipientPlan(
|
|
label=label,
|
|
address=address,
|
|
target_out_raw=target_per_recipient_raw,
|
|
loops=loops,
|
|
gross_in_raw=loops * cw_in_per_loop,
|
|
output_raw=target_per_recipient_raw,
|
|
preview_output_raw=loops * cw_out_per_loop,
|
|
rounding_raw=(loops * cw_out_per_loop) - target_per_recipient_raw,
|
|
neutralized_raw=loops * neutralized_per_loop,
|
|
virtual_debt_raw=loops * DEBT_PER_LOOP_RAW,
|
|
)
|
|
)
|
|
|
|
total_gross = sum(p.gross_in_raw for p in recipient_plans)
|
|
total_output = sum(p.output_raw for p in recipient_plans)
|
|
total_neutralized = sum(p.neutralized_raw for p in recipient_plans)
|
|
minimum_bridge_needed = max(0, total_gross - mainnet_cwusdc)
|
|
exact_target_total = sum(p.target_out_raw for p in recipient_plans)
|
|
|
|
bridge_report: dict[str, Any] = {"configured": bool(bridge)}
|
|
if bridge:
|
|
fee_token = first_address(run(["cast", "call", bridge, "feeToken()(address)", "--rpc-url", rpc138], allow_fail=True))
|
|
bridge_report["address"] = bridge
|
|
bridge_report["feeToken"] = fee_token
|
|
bridge_report["destination"] = run(
|
|
["cast", "call", bridge, "destinations(address,uint64)(address,bool)", cusdc, str(MAINNET_SELECTOR), "--rpc-url", rpc138],
|
|
allow_fail=True,
|
|
)
|
|
if fee_token:
|
|
bridge_report["feeTokenBalanceRaw"] = str(
|
|
first_uint(run(["cast", "call", fee_token, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc138], allow_fail=True)) or 0
|
|
)
|
|
bridge_report["feeTokenAllowanceRaw"] = str(
|
|
first_uint(
|
|
run(
|
|
["cast", "call", fee_token, "allowance(address,address)(uint256)", deployer, bridge, "--rpc-url", rpc138],
|
|
allow_fail=True,
|
|
)
|
|
)
|
|
or 0
|
|
)
|
|
bridge_report["cusdcAllowanceRaw"] = str(
|
|
first_uint(run(["cast", "call", cusdc, "allowance(address,address)(uint256)", deployer, bridge, "--rpc-url", rpc138], allow_fail=True))
|
|
or 0
|
|
)
|
|
bridge_report["minimumBridgeFeeRaw"] = str(
|
|
first_uint(
|
|
run(
|
|
[
|
|
"cast",
|
|
"call",
|
|
bridge,
|
|
"calculateFee(address,uint64,address,uint256)(uint256)",
|
|
cusdc,
|
|
str(MAINNET_SELECTOR),
|
|
deployer,
|
|
str(minimum_bridge_needed or 1),
|
|
"--rpc-url",
|
|
rpc138,
|
|
],
|
|
allow_fail=True,
|
|
)
|
|
)
|
|
or 0
|
|
)
|
|
bridge_report["ethCallLockAndSend"] = run(
|
|
[
|
|
"cast",
|
|
"call",
|
|
bridge,
|
|
"lockAndSend(address,uint64,address,uint256)(bytes32)",
|
|
cusdc,
|
|
str(MAINNET_SELECTOR),
|
|
deployer,
|
|
str(minimum_bridge_needed or 1),
|
|
"--from",
|
|
deployer,
|
|
"--rpc-url",
|
|
rpc138,
|
|
],
|
|
allow_fail=True,
|
|
)
|
|
|
|
blockers: list[str] = []
|
|
if pool_cw != pool_usdc:
|
|
blockers.append("maintained vault reserves are not 1:1; virtual batch must not run")
|
|
if lender < DEBT_PER_LOOP_RAW:
|
|
blockers.append("maintained lender bucket is below 5 USDC")
|
|
if minimum_bridge_needed > chain138_cusdc:
|
|
blockers.append("Chain 138 cUSDC balance is below required bridge amount")
|
|
if not bridge:
|
|
blockers.append("CW_L1_BRIDGE_CHAIN138 is not configured")
|
|
elif "true" not in str(bridge_report.get("destination", "")).lower():
|
|
blockers.append("cUSDC -> Ethereum Mainnet bridge destination is not enabled")
|
|
if total_gross > mainnet_cwusdc and minimum_bridge_needed == 0:
|
|
blockers.append("internal planner error: gross exceeds balance but bridge amount is zero")
|
|
|
|
amount_mode_note = (
|
|
"per_recipient_5b"
|
|
if not args.total and target_per_recipient_raw == raw_from_human("5000000000")
|
|
else "custom"
|
|
)
|
|
if amount_mode_note == "per_recipient_5b":
|
|
total_5b_bridge_shortfall = max(0, total_gross - raw_from_human("5000000000") - mainnet_cwusdc)
|
|
else:
|
|
total_5b_bridge_shortfall = None
|
|
|
|
payload: dict[str, Any] = {
|
|
"schema": "dbis-engine-x-recipient-deposit-plan/v1",
|
|
"generatedAt": datetime.now(timezone.utc).isoformat(),
|
|
"classification": "read_only_preflight_no_broadcast",
|
|
"deployer": deployer,
|
|
"recipients": [
|
|
{
|
|
"label": p.label,
|
|
"address": p.address,
|
|
"targetOutRaw": str(p.target_out_raw),
|
|
"targetOut": human(p.target_out_raw),
|
|
"virtualLoops": p.loops,
|
|
"grossCwusdcInputRaw": str(p.gross_in_raw),
|
|
"grossCwusdcInput": human(p.gross_in_raw),
|
|
"cwusdcOutputRaw": str(p.output_raw),
|
|
"cwusdcOutput": human(p.output_raw),
|
|
"previewCwusdcOutputRaw": str(p.preview_output_raw),
|
|
"previewCwusdcOutput": human(p.preview_output_raw),
|
|
"roundingRaw": str(p.rounding_raw),
|
|
"rounding": human(p.rounding_raw),
|
|
"neutralizedRaw": str(p.neutralized_raw),
|
|
"neutralized": human(p.neutralized_raw),
|
|
"virtualDebtUsdcRaw": str(p.virtual_debt_raw),
|
|
"virtualDebtUsdc": human(p.virtual_debt_raw),
|
|
}
|
|
for p in recipient_plans
|
|
],
|
|
"engineX": {
|
|
"maintainedVault": maintained_vault,
|
|
"virtualBatchContract": "smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol",
|
|
"debtPerLoopRaw": str(DEBT_PER_LOOP_RAW),
|
|
"debtPerLoop": human(DEBT_PER_LOOP_RAW),
|
|
"poolCwusdcReserveRaw": str(pool_cw),
|
|
"poolCwusdcReserve": human(pool_cw),
|
|
"poolUsdcReserveRaw": str(pool_usdc),
|
|
"poolUsdcReserve": human(pool_usdc),
|
|
"lenderUsdcRaw": str(lender),
|
|
"lenderUsdc": human(lender),
|
|
"cwusdcInPerLoopRaw": str(cw_in_per_loop),
|
|
"cwusdcInPerLoop": human(cw_in_per_loop),
|
|
"cwusdcOutPerLoopRaw": str(cw_out_per_loop),
|
|
"cwusdcOutPerLoop": human(cw_out_per_loop),
|
|
"neutralizedPerLoopRaw": str(neutralized_per_loop),
|
|
"neutralizedPerLoop": human(neutralized_per_loop),
|
|
"xautCollateralPerBatchRaw": str(xaut_collateral),
|
|
"xautCollateralPerBatch": human(xaut_collateral),
|
|
},
|
|
"balances": {
|
|
"chain138CusdcRaw": str(chain138_cusdc),
|
|
"chain138Cusdc": human(chain138_cusdc),
|
|
"mainnetCwusdcRaw": str(mainnet_cwusdc),
|
|
"mainnetCwusdc": human(mainnet_cwusdc),
|
|
"mainnetEthWei": str(mainnet_eth),
|
|
"mainnetGasPriceWei": str(mainnet_gas_price),
|
|
},
|
|
"totals": {
|
|
"exactTargetOutputRaw": str(exact_target_total),
|
|
"exactTargetOutput": human(exact_target_total),
|
|
"grossCwusdcInputRaw": str(total_gross),
|
|
"grossCwusdcInput": human(total_gross),
|
|
"cwusdcOutputRaw": str(total_output),
|
|
"cwusdcOutput": human(total_output),
|
|
"neutralizedRaw": str(total_neutralized),
|
|
"neutralized": human(total_neutralized),
|
|
"minimumAdditionalBridgeRaw": str(minimum_bridge_needed),
|
|
"minimumAdditionalBridge": human(minimum_bridge_needed),
|
|
"chain138CusdcAfterMinimumBridgeRaw": str(chain138_cusdc - minimum_bridge_needed),
|
|
"chain138CusdcAfterMinimumBridge": human(chain138_cusdc - minimum_bridge_needed),
|
|
"shortfallIfOnly5bBridgedRaw": str(total_5b_bridge_shortfall) if total_5b_bridge_shortfall is not None else None,
|
|
"shortfallIfOnly5bBridged": human(total_5b_bridge_shortfall) if total_5b_bridge_shortfall is not None else None,
|
|
},
|
|
"bridge": bridge_report,
|
|
"blockers": blockers,
|
|
"gapsAndInconsistencies": [
|
|
{
|
|
"id": "amount-semantics",
|
|
"finding": "5B cWUSDC to each of two wallets is a 10B final-output plan, not a 5B total bridge plan.",
|
|
"recommendation": "Use at least the computed minimum additional bridge amount, or bridge a rounded 10B cUSDC tranche and use existing Mainnet cWUSDC as gas/rounding headroom.",
|
|
},
|
|
{
|
|
"id": "engine-x-before-recipient",
|
|
"finding": "If cUSDC is bridged directly to the recipient wallets, the deployer cannot run Engine X over that cWUSDC without recipient approvals.",
|
|
"recommendation": "Bridge to the deployer first, run Engine X `runVirtualProofTo` for each recipient, then let Engine X deliver the final cWUSDC output.",
|
|
},
|
|
{
|
|
"id": "contract-not-deployed",
|
|
"finding": "The live maintained vault cannot run virtual batches or direct output to arbitrary recipients.",
|
|
"recommendation": "Deploy `DBISEngineXVirtualBatchVault`, seed it from the maintained vault resources, and verify source before any 5B recipient proof.",
|
|
},
|
|
{
|
|
"id": "surplus-receiver",
|
|
"finding": "The surplus receiver changes the economic meaning of neutralized cWUSDC.",
|
|
"recommendation": "Use deployer as surplus receiver to conserve deployer-controlled cWUSDC; use a neutral lock or treasury receiver if the proof must show real cWUSDC removal from active deployer control.",
|
|
},
|
|
{
|
|
"id": "bridge-introspection",
|
|
"finding": "The deployed Chain 138 bridge has an older runtime ABI: destination and fee checks work, but several newer capacity getters revert.",
|
|
"recommendation": "Treat the successful `lockAndSend` eth_call as the current readiness check, and run a canary before any multi-billion bridge.",
|
|
},
|
|
{
|
|
"id": "accounting-not-public-volume",
|
|
"finding": "Engine X virtual batches are accounting / solvency proofs, not public DEX volume or public cWUSDC/USDC peg repair.",
|
|
"recommendation": "Keep public listing, DEX liquidity, and Engine X recipient-deposit evidence separated in docs and submissions.",
|
|
},
|
|
{
|
|
"id": "ccip-asynchronous",
|
|
"finding": "The bridge leg and Mainnet Engine X leg cannot be one atomic cross-chain transaction with the current bridge.",
|
|
"recommendation": "Use a staged runbook: bridge, confirm Mainnet mint, then approve and run Engine X recipient deposits.",
|
|
},
|
|
{
|
|
"id": "loop-granularity",
|
|
"finding": "Current loop sizing creates a small output rounding amount because preview outputs are loop multiples.",
|
|
"recommendation": "Use `runVirtualProofExactOutTo(...)` so each wallet receives exactly 5B and the rounding amount is routed to the configured rounding receiver.",
|
|
},
|
|
],
|
|
"operatorCommands": {
|
|
"note": "Review-only. Do not broadcast until recipient amount semantics and surplus receiver are confirmed.",
|
|
"bridgeMinimumToDeployer": (
|
|
f'cast send "$CW_L1_BRIDGE_CHAIN138" '
|
|
f'"lockAndSend(address,uint64,address,uint256)" "$CUSDC_ADDRESS_138" {MAINNET_SELECTOR} '
|
|
f"{deployer} {minimum_bridge_needed} --rpc-url \"$RPC_URL_138\" --private-key \"$PRIVATE_KEY\""
|
|
),
|
|
"engineXRecipientCalls": [
|
|
f'cast send "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" '
|
|
f'"runVirtualProofExactOutTo(bytes32,uint256,uint256,address,uint256,address,bytes32,bytes32,bytes32)" '
|
|
f'$(cast keccak "dbis-engine-x:{p.label}:5b:{p.loops}") {DEBT_PER_LOOP_RAW} {p.loops} '
|
|
f'{p.address} {p.target_out_raw} "$DBIS_ENGINE_X_ROUNDING_RECEIVER" '
|
|
f'"$DBIS_ENGINE_X_ISO20022_HASH" "$DBIS_ENGINE_X_AUDIT_HASH" "$DBIS_ENGINE_X_PEG_HASH" '
|
|
f'--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"'
|
|
for p in recipient_plans
|
|
],
|
|
},
|
|
}
|
|
|
|
json_path = Path(args.json_out)
|
|
md_path = Path(args.md_out)
|
|
json_path.parent.mkdir(parents=True, exist_ok=True)
|
|
md_path.parent.mkdir(parents=True, exist_ok=True)
|
|
json_path.write_text(json.dumps(payload, indent=2) + "\n")
|
|
md_path.write_text(render_markdown(payload) + "\n")
|
|
print(json.dumps({"json": str(json_path), "markdown": str(md_path), "blockers": blockers}, indent=2))
|
|
return 0
|
|
|
|
|
|
def render_markdown(payload: dict[str, Any]) -> str:
|
|
lines: list[str] = []
|
|
lines.append("# DBIS Engine X Recipient Deposit Plan")
|
|
lines.append("")
|
|
lines.append(f"Generated: `{payload['generatedAt']}`")
|
|
lines.append("")
|
|
lines.append("Classification: read-only preflight. No transaction was broadcast.")
|
|
lines.append("")
|
|
lines.append("## Summary")
|
|
lines.append("")
|
|
totals = payload["totals"]
|
|
balances = payload["balances"]
|
|
lines.append(f"- Exact target output: `{totals['exactTargetOutput']} cWUSDC`")
|
|
lines.append(f"- Gross Engine X cWUSDC input: `{totals['grossCwusdcInput']} cWUSDC`")
|
|
lines.append(f"- Exact Engine X recipient output: `{totals['cwusdcOutput']} cWUSDC`")
|
|
lines.append(f"- Neutralized cWUSDC: `{totals['neutralized']} cWUSDC`")
|
|
lines.append(f"- Current Mainnet cWUSDC: `{balances['mainnetCwusdc']} cWUSDC`")
|
|
lines.append(f"- Minimum additional cUSDC bridge: `{totals['minimumAdditionalBridge']} cUSDC`")
|
|
lines.append(f"- Chain 138 cUSDC after minimum bridge: `{totals['chain138CusdcAfterMinimumBridge']} cUSDC`")
|
|
if totals.get("shortfallIfOnly5bBridged"):
|
|
lines.append(f"- Shortfall if only `5,000,000,000` cUSDC is bridged: `{totals['shortfallIfOnly5bBridged']} cWUSDC`")
|
|
lines.append("")
|
|
lines.append("## Recipients")
|
|
lines.append("")
|
|
lines.append("| Label | Address | Target output | Virtual loops | Gross input | Exact output | Rounding | Neutralized |")
|
|
lines.append("|---|---|---:|---:|---:|---:|---:|---:|")
|
|
for r in payload["recipients"]:
|
|
lines.append(
|
|
f"| `{r['label']}` | `{r['address']}` | `{r['targetOut']}` | `{r['virtualLoops']:,}` | "
|
|
f"`{r['grossCwusdcInput']}` | `{r['cwusdcOutput']}` | `{r['rounding']}` | `{r['neutralized']}` |"
|
|
)
|
|
lines.append("")
|
|
lines.append("## Engine X Basis")
|
|
lines.append("")
|
|
ex = payload["engineX"]
|
|
lines.append(f"- Maintained vault anchor: `{ex['maintainedVault']}`")
|
|
lines.append(f"- New virtual-batch contract source: `{ex['virtualBatchContract']}`")
|
|
lines.append(f"- Pool: `{ex['poolCwusdcReserve']} cWUSDC / {ex['poolUsdcReserve']} USDC`")
|
|
lines.append(f"- Lender bucket: `{ex['lenderUsdc']} USDC`")
|
|
lines.append(f"- Per loop: `{ex['cwusdcInPerLoop']} in / {ex['cwusdcOutPerLoop']} out / {ex['neutralizedPerLoop']} neutralized`")
|
|
lines.append(f"- XAUt collateral floor per virtual batch: `{ex['xautCollateralPerBatch']} XAUt`")
|
|
lines.append("")
|
|
lines.append("## Bridge")
|
|
lines.append("")
|
|
bridge = payload["bridge"]
|
|
if bridge.get("configured"):
|
|
lines.append(f"- Chain 138 bridge: `{bridge.get('address')}`")
|
|
lines.append(f"- Fee token: `{bridge.get('feeToken')}`")
|
|
lines.append(f"- Mainnet destination check: `{bridge.get('destination')}`")
|
|
lines.append(f"- Estimated minimum bridge fee raw: `{bridge.get('minimumBridgeFeeRaw')}`")
|
|
lines.append(f"- lockAndSend eth_call: `{bridge.get('ethCallLockAndSend')}`")
|
|
else:
|
|
lines.append("- Chain 138 bridge is not configured.")
|
|
lines.append("")
|
|
lines.append("## Blockers")
|
|
lines.append("")
|
|
blockers = payload.get("blockers") or []
|
|
if blockers:
|
|
for blocker in blockers:
|
|
lines.append(f"- {blocker}")
|
|
else:
|
|
lines.append("- No read-only preflight blockers found.")
|
|
lines.append("")
|
|
lines.append("## Gaps And Inconsistencies")
|
|
lines.append("")
|
|
lines.append("| ID | Finding | Recommendation |")
|
|
lines.append("|---|---|---|")
|
|
for item in payload.get("gapsAndInconsistencies", []):
|
|
lines.append(f"| `{item['id']}` | {item['finding']} | {item['recommendation']} |")
|
|
lines.append("")
|
|
lines.append("## Recommendations")
|
|
lines.append("")
|
|
lines.append("1. Treat this as a two-stage cross-chain operation: bridge to deployer, wait for Mainnet cWUSDC mint, then run Engine X recipient deposits.")
|
|
lines.append("2. Bridge a rounded `10,000,000,000 cUSDC` tranche rather than exactly the minimum if the surplus receiver is deployer-controlled; bridge the computed gross requirement if the surplus receiver is a neutral lock/treasury.")
|
|
lines.append("3. Run a small canary first through the same recipient path before any billion-scale transaction.")
|
|
lines.append("4. Deploy and verify `DBISEngineXVirtualBatchVault` only after selecting the surplus receiver and rounding receiver.")
|
|
lines.append("5. Keep Mainnet ETH reserve for deploy, approvals, verification, and the two Engine X recipient calls; do not spend the full deployer ETH balance.")
|
|
lines.append("6. Record CCIP message IDs, Mainnet mint events, Engine X proof IDs, and recipient balances in the final evidence report.")
|
|
lines.append("")
|
|
lines.append("## Operator Notes")
|
|
lines.append("")
|
|
lines.append("- The phrase `5B to each wallet` means `10B` final cWUSDC output across the two listed wallets.")
|
|
lines.append("- Bridging exactly `5B` total is not enough for `5B` output to each wallet.")
|
|
lines.append("- The virtual-batch vault must be deployed before the Engine X recipient calls can run.")
|
|
lines.append("- The surplus receiver must be chosen before deployment: deployer conserves cWUSDC control; lock/treasury proves stronger neutralization.")
|
|
lines.append("- Commands in the JSON are review-only and must not be broadcast until the amount semantics are confirmed.")
|
|
return "\n".join(lines)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|