diff --git a/.gitignore b/.gitignore index 994c2332..992bf195 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ reports/status/MULTI_NETWORK_DEPLOYMENT_AUDIT_*.md reports/status/*-latest.json reports/status/*-latest.md reports/status/*-latest.csv +reports/status/*-latest.xml reports/status/hardware_poll_*.txt reports/status/lxc_cluster_health_*.json reports/status/lxc_cluster_health_*.txt diff --git a/docs/03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md b/docs/03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md new file mode 100644 index 00000000..ea03502a --- /dev/null +++ b/docs/03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md @@ -0,0 +1,108 @@ +# DBIS Engine X Recipient Proof Runbook + +**Status:** pre-deployment proof package +**Scope:** Chain 138 `cUSDC` -> Ethereum Mainnet `cWUSDC` funding, Engine X maintained accounting rail, exact-output recipient deposits, ISO 20022-style evidence, and on-chain hash anchoring. + +## Purpose + +This runbook is the durable operator path for the DBIS Engine X proof package where `5,000,000,000 cWUSDC` is delivered to each configured recipient wallet. + +The current implementation proves the Engine X internal maintained rail, not public DEX market depth. A public `cWUSDC/USDC` peg still requires separate public liquidity and quote evidence. + +## Proof Boundaries + +| Claim | Status | Evidence | +|---|---|---| +| Exact recipient output | Implemented | `DBISEngineXVirtualBatchVault.runVirtualProofExactOutTo(...)` and recipient planner | +| Engine X internal `cWUSDC ~= USDC` peg throughout batch | Implemented | Virtual batch requires equal maintained reserves before execution and leaves reserves unchanged | +| ISO 20022-style transfer evidence | Implemented | `head.001.001.03` application header + `pacs.008.001.13` credit transfer XML with DBIS supplementary proof data | +| Online proof package | Ready after publication | Timestamped plan, ISO XML, peg proof, audit envelope, and proof hashes under `reports/status/` | +| On-chain proof anchor | Ready after deployment/broadcast | `VirtualProofAuditEvidence` emits ISO/audit/peg hashes per recipient proof | +| Legal/regulatory approval | Not claimed | Requires external legal, compliance, AML/KYC, sanctions, and auditor evidence | +| Public DEX peg repair | Not claimed | Requires separate public `cWUSDC/USDC` liquidity, quote, and reserve evidence | + +Official ISO references used by this package: + +- ISO 20022 standard: +- ISO 20022 message definitions: +- ISO 20022 FAQ/certification note: + +## Implemented Components + +| Component | Path | +|---|---| +| Virtual batch proof vault | `smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol` | +| Virtual batch tests | `smom-dbis-138/test/flash/DBISEngineXVirtualBatchVault.t.sol` | +| Recipient deposit planner | `scripts/verify/plan-dbis-engine-x-recipient-deposits.py` | +| Planner wrapper | `scripts/verify/plan-dbis-engine-x-recipient-deposits.sh` | +| ISO/audit proof generator | `scripts/verify/generate-dbis-engine-x-iso20022-proofs.py` | +| Proof package wrapper | `scripts/verify/build-dbis-engine-x-proof-package.sh` | +| Canary preflight and canary hash generator | `scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.py` | +| Main status report | `reports/status/dbis-engine-x-5b-cwusdc-ladder-recalc-20260506.md` | + +## Build The Proof Package + +```bash +pnpm engine-x:proof-package --per-recipient 5000000000 +``` + +Optional reproducible run: + +```bash +DBIS_ENGINE_X_SNAPSHOT_TAG=20260507 \ +DBIS_ENGINE_X_GENERATED_AT=2026-05-07T00:00:00+00:00 \ +pnpm engine-x:proof-package --per-recipient 5000000000 +``` + +The wrapper emits: + +- `reports/status/dbis-engine-x-recipient-deposit-plan-.json` +- `reports/status/dbis-engine-x-recipient-deposit-plan-.md` +- `reports/status/dbis-engine-x-recipient-deposit-iso20022-.xml` +- `reports/status/dbis-engine-x-recipient-deposit-peg-proof-.json` +- `reports/status/dbis-engine-x-recipient-deposit-audit-envelope-.json` +- `reports/status/dbis-engine-x-recipient-deposit-proof-hashes-.json` + +## On-Chain Anchor Flow + +Do not broadcast from this runbook until the deployment wallet, surplus receiver, rounding receiver, and bridge tranche are explicitly confirmed. + +1. Run the canary preflight: + +```bash +pnpm engine-x:canary-preflight +``` + +2. Deploy and verify `DBISEngineXVirtualBatchVault`. +3. Seed the virtual batch vault with the canary `cWUSDC/USDC` rail and fund the canary lender bucket. +4. Run `runVirtualProofExactOutTo(...)` for the canary using the canary ISO/audit/peg hashes. +5. Save the canary deploy, seed, fund, proof, and final reserve evidence. +6. Bridge the required Chain 138 `cUSDC` to the deployer on Mainnet, not directly to recipients. +7. Confirm the Mainnet `cWUSDC` mint and deployer balances. +8. Export the 5B proof hashes from `reports/status/dbis-engine-x-recipient-deposit-proof-hashes-.json`. +9. Approve `cWUSDC` and `XAUt` to the virtual batch vault. +10. Run `runVirtualProofExactOutTo(...)` for each recipient. +11. Save the bridge transaction hash, Mainnet mint event, proof transaction hashes, emitted proof IDs, and final recipient balances. + +If the deployer wallet has no official Mainnet USDC, the canary preflight will recommend a tiny `XAUt -> USDC` prep swap. Do not reuse the 5B recipient proof hashes for this canary; use the canary hashes generated by `pnpm engine-x:canary-preflight`. + +## Peg Maintenance Rule + +Engine X proof execution must satisfy all of these conditions: + +- `poolCwusdcReserve == poolUsdcReserve` before proof execution. +- The virtual proof preview passes the configured maximum round-trip loss. +- The recipient exact output is less than or equal to the preview output. +- The proof event emits nonzero ISO 20022, audit envelope, and peg proof hashes. +- The vault leaves `poolCwusdcReserve == poolUsdcReserve` after execution. + +This proves the maintained Engine X internal accounting rail. It does not prove public market price discovery or public DEX volume. + +## Remaining Deployment Gates + +- Select the surplus receiver and rounding receiver. +- Deploy and verify `DBISEngineXVirtualBatchVault`. +- Run a small canary before the full recipient path. +- Publish the timestamped proof package online. +- Anchor the proof hashes on-chain with the exact-output recipient calls. +- Attach external compliance evidence when required by jurisdiction or counterparty policy. diff --git a/docs/MASTER_INDEX.md b/docs/MASTER_INDEX.md index 7d23bcbc..a93329b5 100644 --- a/docs/MASTER_INDEX.md +++ b/docs/MASTER_INDEX.md @@ -37,6 +37,7 @@ | **Source to CEX production readiness** | [03-deployment/SOURCE_TO_CEX_PRODUCTION_READINESS.md](03-deployment/SOURCE_TO_CEX_PRODUCTION_READINESS.md) — repo-native readiness gate for immediate production | | **Immediate live production task list: source to CEX** | [03-deployment/IMMEDIATE_LIVE_PRODUCTION_TASK_LIST_SOURCE_TO_CEX.md](03-deployment/IMMEDIATE_LIVE_PRODUCTION_TASK_LIST_SOURCE_TO_CEX.md) — task list with remaining live blockers called out | | **ALL Mainnet protocol completion** | [03-deployment/ALL_MAINNET_PROTOCOL_COMPLETION_RUNBOOK.md](03-deployment/ALL_MAINNET_PROTOCOL_COMPLETION_RUNBOOK.md) — required inventory pools, funding/canary gates, auto-rebalancing path, and protocol enablement order for DODO, Uniswap, Balancer, Curve, Sushi, 1inch, and Aave | +| **DBIS Engine X recipient proof package** | [03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md](03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md) — 5B-each `cWUSDC` recipient proof path, virtual-batch vault, ISO 20022-style evidence, audit envelope, and on-chain hash-anchor flow | | **External dependency blockers** | [03-deployment/EXTERNAL_DEPENDENCY_BLOCKERS.md](03-deployment/EXTERNAL_DEPENDENCY_BLOCKERS.md) — explicit list of items that cannot be closed by repo-only changes, with readiness checks and env knobs | | **Crypto.com OTC before vs after matrix** | [03-deployment/CRYPTO_COM_OTC_BEFORE_AFTER_OPERATOR_MATRIX.md](03-deployment/CRYPTO_COM_OTC_BEFORE_AFTER_OPERATOR_MATRIX.md) — strict operator comparison of the current ecosystem versus the state after a real Crypto.com OTC sink is connected | | **Provider-facing source to CEX package** | [03-deployment/PROVIDER_FACING_PACKAGE_SOURCE_TO_CEX.md](03-deployment/PROVIDER_FACING_PACKAGE_SOURCE_TO_CEX.md) — strict provider-facing package covering expectations, flow presentation, questions, and a first 30-day ramp plan | diff --git a/package.json b/package.json index 9263191c..fa8fbaec 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,11 @@ "all-mainnet:official-dodo-migration": "node scripts/status/execute-official-dodo-migration.mjs", "all-mainnet:remaining-routing-tasks": "node scripts/status/build-remaining-official-routing-tasks.mjs", "all-mainnet:remaining-balances": "node scripts/status/check-remaining-deployer-balances.mjs", - "all-mainnet:oneinch-preflight": "node scripts/status/check-oneinch-remaining-routes.mjs" + "all-mainnet:oneinch-preflight": "node scripts/status/check-oneinch-remaining-routes.mjs", + "engine-x:recipient-plan": "bash scripts/verify/plan-dbis-engine-x-recipient-deposits.sh", + "engine-x:iso20022-proofs": "bash scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh", + "engine-x:proof-package": "bash scripts/verify/build-dbis-engine-x-proof-package.sh", + "engine-x:canary-preflight": "bash scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.sh" }, "keywords": [ "proxmox", diff --git a/reports/status/dbis-engine-x-5b-cwusdc-ladder-recalc-20260506.md b/reports/status/dbis-engine-x-5b-cwusdc-ladder-recalc-20260506.md index bdc82744..d65d5c36 100644 --- a/reports/status/dbis-engine-x-5b-cwusdc-ladder-recalc-20260506.md +++ b/reports/status/dbis-engine-x-5b-cwusdc-ladder-recalc-20260506.md @@ -1185,3 +1185,399 @@ XAUt allowance / balance cWUSDC allowance / balance 5 USDC lender bucket ``` + +## Virtual Batch Optimization + +Reviewed and implemented: 2026-05-07 + +The maintained vault solved reserve drift, but `runProof(debt=5 USDC, loops=3)` still settles each loop on-chain. At that rate, `5,000,000,000 cWUSDC` needs approximately: + +```text +per-loop cWUSDC in: 5.325523 +per-loop cWUSDC returned: 5.295471 +per-loop neutralized: 0.030052 +round-trip loss: ~0.564301% +loops for 5B gross input: 938,874,924 +3-loop transactions: 312,958,308 +gas at 180,724 per tx: 56,559,077,254,992 gas +ETH at 2.560197890 gwei: ~144,802.430249 ETH +``` + +That is the reason the non-batched path would take years. The blocker is not the math; it is per-loop transaction overhead. + +### Implemented Contract + +New contract: + +```text +smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol +``` + +Purpose: + +```text +Compress identical maintained Engine X loops into one net-settled accounting proof. +``` + +Important classification: + +```text +This is an accounting / solvency proof. +It is not public DEX volume. +It is not listing-quality public spot liquidity. +It does not repair the public cWUSDC/USDC UniV2 peg by itself. +``` + +The virtual batch contract requires the proof pool to start maintained: + +```text +poolCwusdcReserve == poolUsdcReserve +lenderUsdcAvailable >= debtUsdcPerLoop +roundTripLoss <= maxRoundTripLossBps +``` + +Then it computes one maintained loop and multiplies the totals by `virtualLoops`. The vault performs one net settlement: + +```text +transfer total cWUSDC input from operator +transfer total cWUSDC output back to operator +transfer total neutralized cWUSDC to surplusReceiver +return XAUt collateral +leave pool reserves unchanged at 1:1 +``` + +This changes the throughput limit from transaction count to available cWUSDC balance and allowance. + +### Current Mainnet State + +Read at 2026-05-07T13:11:22Z: + +```text +maintained vault: 0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6 +deployer: 0x4A666F96fC8764181194447A7dFdb7d471b301C8 +gas price: 2.560197890 gwei + +wallet ETH: 0.013562022271250384 +wallet cWUSDC: 70,390,560.890977 +wallet USDC: 0 +wallet XAUt: 0.007474 + +maintained pool cWUSDC: 85.763529 +maintained pool USDC: 85.763529 +maintained lender USDC: 5.000000 +maintained surplus: 0 +total neutralized so far: 0.090156 + +current cWUSDC allowance to maintained vault: 984.023431 +current XAUt allowance to maintained vault: 0.001663 +``` + +The current wallet has enough XAUt balance for the optimized proof collateral, but the live maintained-vault XAUt allowance is below the `0.001937 XAUt` floor for a `5 USDC` loop. A newly deployed virtual batch vault would need fresh approvals. + +### Optimized Sizing + +With the current `85.763529 / 85.763529` maintained rail and `5 USDC` reusable lender bucket: + +| Scope | Virtual loops | Gross cWUSDC input | cWUSDC returned | cWUSDC neutralized | Virtual debt cycled | +|---|---:|---:|---:|---:|---:| +| Current maintained-vault allowance only | `184` | `979.896232` | `974.366664` | `5.529568` | `920 USDC` | +| Current wallet cWUSDC balance | `13,217,586` | `70,390,558.247478` | `69,993,343.353006` | `397,214.894472` | `66,087,930 USDC` | +| Full `5B` target | `938,874,924` | `5,000,000,001.885252` | `4,971,784,932.669204` | `28,215,069.216048` | `4,694,374,620 USDC` | + +The optimized model keeps the `5 USDC` lender bucket reusable because each virtual loop closes before the next virtual loop. It needs only the single-loop XAUt collateral floor, currently modeled as: + +```text +XAUt collateral per virtual batch: 0.001937 XAUt +``` + +That collateral is not multiplied by `virtualLoops` because the loops are sequential in the accounting model. + +### New Bottlenecks + +Virtual batching removes the years-long transaction count, but it does not remove these limits: + +```text +1. The operator must hold or source the gross cWUSDC input for the batch. +2. The operator must approve the virtual batch vault for that cWUSDC input. +3. The proof remains internal accounting throughput, not public market volume. +4. If surplusReceiver is the deployer, cWUSDC is only neutralized out of pool reserves, not out of deployer control. +5. If the goal is true cWUSDC reduction, surplusReceiver should be a neutral lock, burn, or treasury receiver. +``` + +Current wallet cWUSDC can cover about: + +```text +70,390,558.247478 / 5,000,000,000 ~= 1.407811% +``` + +of the full 5B gross target. The remaining blocker is cWUSDC inventory, not loop speed. + +### Recommended Optimization Path + +1. Keep the current maintained vault as the live proof anchor. +2. Treat `DBISEngineXVirtualBatchVault` as the next proof contract for high-throughput accounting batches. +3. Choose the surplus receiver before deployment: + - deployer receiver: proves pool-neutralized throughput, but does not reduce deployer-controlled cWUSDC. + - neutral lock / treasury receiver: proves real cWUSDC removal from the active operator balance. +4. Deploy and seed the virtual batch vault only after the receiver choice is final. +5. Run a small virtual batch first, then scale to the full current wallet balance. +6. Do not describe the virtual batch as public DEX volume or public price repair. + +### Validation + +Completed: + +```text +bash scripts/forge/scope.sh build flash --contracts contracts/flash/DBISEngineXVirtualBatchVault.sol +bash scripts/forge/scope.sh test flash --match-path 'test/flash/DBISEngineXVirtualBatchVault.t.sol' +``` + +Test coverage added: + +```text +smom-dbis-138/test/flash/DBISEngineXVirtualBatchVault.t.sol +``` + +Covered checks: + +```text +live maintained-loop math matches 5.325523 in / 5.295471 out / 0.030052 neutralized +virtual proof keeps pool cWUSDC == pool USDC +virtual loop count scales totals without multiplying sequential XAUt collateral +duplicate proof ids cannot be reused +unmaintained pools cannot run virtual batches +``` + +## 5B Each Recipient Deposit Preflight + +Reviewed: 2026-05-07 + +New durable planner: + +```text +scripts/verify/plan-dbis-engine-x-recipient-deposits.py +scripts/verify/plan-dbis-engine-x-recipient-deposits.sh +``` + +Latest outputs: + +```text +reports/status/dbis-engine-x-recipient-deposit-plan-latest.json +reports/status/dbis-engine-x-recipient-deposit-plan-latest.md +``` + +Confirmed target semantics: + +```text +Meta wallet: 0x148ca6efce22829d12f17da9b6e169689d6bb8ac +Master wallet: 0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e +Target: 5,000,000,000 cWUSDC to each wallet +Total output: 10,000,000,000 cWUSDC +``` + +Preflight result: + +```text +gross Engine X input required: 10,056,750,385.166450 cWUSDC +Engine X output: 10,000,000,003.546650 cWUSDC +neutralized amount: 56,750,381.619800 cWUSDC +current Mainnet cWUSDC: 70,390,560.890977 cWUSDC +minimum additional cUSDC bridge: 9,986,359,824.275473 cUSDC +current Chain 138 cUSDC: 11,008,717,575.859079 cUSDC +Chain 138 cUSDC after min bridge: 1,022,357,751.583606 cUSDC +``` + +The plan is fundable from the current Chain 138 deployer cUSDC balance, but it is not a single atomic cross-chain transaction. The recommended sequence is: + +```text +1. Bridge cUSDC to deployer on Mainnet as cWUSDC. +2. Wait for Mainnet mint confirmation. +3. Deploy and verify DBISEngineXVirtualBatchVault. +4. Seed/migrate the maintained proof rail. +5. Approve cWUSDC and XAUt. +6. Run runVirtualProofTo(...) once for Meta and once for master. +7. Record recipient balances, proof ids, CCIP message ids, and mint events. +``` + +Important gaps: + +```text +bridging exactly 5B total is not enough for 5B to each wallet +bridging directly to recipient wallets prevents deployer-run Engine X unless recipients approve back +live maintained vault cannot run virtual batches or direct recipient outputs +surplus receiver policy must be chosen before deployment +current Chain 138 bridge runtime lacks newer capacity getters; use canary + eth_call checks +virtual Engine X evidence is accounting/solvency evidence, not public DEX volume +loop granularity creates ~1.773325 cWUSDC rounding per wallet; exact-output function now routes this to roundingReceiver +``` + +## Exact Output, ISO 20022, And Audit Anchor Update + +Implemented: 2026-05-07 + +The recipient path was tightened so each wallet can receive exactly `5,000,000,000.000000 cWUSDC` instead of receiving the loop-multiple overage. + +Contract updates: + +```text +smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol +``` + +New exact-output function: + +```text +runVirtualProofExactOutTo( + bytes32 proofId, + uint256 debtUsdcPerLoop, + uint256 virtualLoops, + address outputRecipient, + uint256 exactOutputAmount, + address roundingReceiver, + bytes32 iso20022DocumentHash, + bytes32 auditEnvelopeHash, + bytes32 pegProofHash +) +``` + +New on-chain audit event: + +```text +VirtualProofAuditEvidence( + proofId, + operator, + outputRecipient, + exactOutputAmount, + outputRoundingAmount, + roundingReceiver, + iso20022DocumentHash, + auditEnvelopeHash, + pegProofHash +) +``` + +Safety/invariant improvements: + +```text +pool must start with poolCwusdcReserve == poolUsdcReserve +lender USDC must cover debtPerLoop +round-trip loss must remain within maxRoundTripLossBps +proofId cannot be reused +exact output cannot exceed preview output +ISO/audit/peg hashes are mandatory for exact-output recipient proofs +seed/fund/proof/withdraw paths are nonReentrant +``` + +New ISO/audit proof generators: + +```text +scripts/verify/generate-dbis-engine-x-iso20022-proofs.py +scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh +scripts/verify/build-dbis-engine-x-proof-package.sh +``` + +Generated proof artifacts: + +```text +reports/status/dbis-engine-x-recipient-deposit-iso20022-latest.xml +reports/status/dbis-engine-x-recipient-deposit-peg-proof-latest.json +reports/status/dbis-engine-x-recipient-deposit-audit-envelope-latest.json +reports/status/dbis-engine-x-recipient-deposit-proof-hashes-latest.json +``` + +Durable 2026-05-07 attached proof snapshot: + +```text +reports/status/dbis-engine-x-recipient-deposit-plan-20260507.json +reports/status/dbis-engine-x-recipient-deposit-plan-20260507.md +reports/status/dbis-engine-x-recipient-deposit-iso20022-20260507.xml +reports/status/dbis-engine-x-recipient-deposit-peg-proof-20260507.json +reports/status/dbis-engine-x-recipient-deposit-audit-envelope-20260507.json +reports/status/dbis-engine-x-recipient-deposit-proof-hashes-20260507.json +``` + +Current proof hashes: + +```text +ISO 20022-style XML SHA-256: 0x16d6db732fa2889ec31d77bad26b26f6598f298bceefe0eee7da9af0b7520f36 +Audit envelope SHA-256: 0x10a8cd2e36917dadf8f32d398d47e230bb0ed4c53f7cb007ea59b73e2e1fac6e +Peg proof SHA-256: 0x7b9c50b48d0e269e8402ecb379d32b755440fdb877b967b8615b43d8e948a3b3 +``` + +The audit package proves the transaction evidence online once published with this repository/report set, and on-chain once the exact-output Engine X calls emit `VirtualProofAuditEvidence` with the hashes above. It is not a legal opinion, regulator approval, AML/KYC clearance, sanctions-screening result, or external auditor attestation. The ISO artifact is an ISO 20022-style evidence envelope using `head.001.001.03` and `pacs.008.001.13` namespaces plus DBIS supplementary proof data; it is not an ISO certification. + +Updated recipient totals: + +```text +Meta exact output: 5,000,000,000.000000 cWUSDC +Master exact output: 5,000,000,000.000000 cWUSDC +Total exact output: 10,000,000,000.000000 cWUSDC +Total gross input: 10,056,750,385.166450 cWUSDC +Total rounding: 3.546650 cWUSDC +Total neutralized: 56,750,381.619800 cWUSDC +``` + +Peg proof scope: + +```text +Proven: Engine X internal maintained accounting rail remains 1:1 throughout the virtual batch. +Not proven by this path: public UniV2/DODO market peg or listing-quality public DEX depth. +``` + +Validation: + +```text +python3 -m py_compile scripts/verify/plan-dbis-engine-x-recipient-deposits.py scripts/verify/generate-dbis-engine-x-iso20022-proofs.py +bash -n scripts/verify/plan-dbis-engine-x-recipient-deposits.sh scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh scripts/verify/build-dbis-engine-x-proof-package.sh +bash scripts/verify/plan-dbis-engine-x-recipient-deposits.sh --per-recipient 5000000000 +bash scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh +pnpm engine-x:proof-package --per-recipient 5000000000 +bash scripts/forge/scope.sh test flash --match-path 'test/flash/DBISEngineXVirtualBatchVault.t.sol' +bash scripts/forge/scope.sh build flash --contracts contracts/flash/DBISEngineXVirtualBatchVault.sol +``` + +Durable runbook: + +```text +docs/03-deployment/DBIS_ENGINE_X_RECIPIENT_PROOF_RUNBOOK.md +``` + +## Deployment Canary Preflight + +Implemented: 2026-05-07 + +The deployment path now has a separate canary preflight so the small live canary does not reuse the 5B recipient proof hashes. + +New command: + +```text +pnpm engine-x:canary-preflight +``` + +New canary artifacts: + +```text +reports/status/dbis-engine-x-virtual-batch-canary-preflight-latest.json +reports/status/dbis-engine-x-virtual-batch-canary-preflight-latest.md +reports/status/dbis-engine-x-virtual-batch-canary-iso20022-latest.xml +reports/status/dbis-engine-x-virtual-batch-canary-peg-proof-latest.json +reports/status/dbis-engine-x-virtual-batch-canary-audit-envelope-latest.json +reports/status/dbis-engine-x-virtual-batch-canary-proof-hashes-latest.json +``` + +The canary uses a minimal internal rail: + +```text +seed: 1.000000 cWUSDC / 1.000000 USDC +lender: 0.010000 USDC +debt: 0.001000 USDC +exact output: computed from live constant-product math +recipient: deployer by default +``` + +Current deployment/canary caveat: + +```text +deployer official Mainnet USDC is 0. +The canary therefore needs either a tiny XAUt -> USDC prep swap, an external USDC top-up, or explicit retirement/migration of the older maintained proof vault. +Do not migrate the old maintained vault silently because its withdraw function transfers tokens without decrementing accounting reserves. +``` diff --git a/reports/status/dbis-engine-x-recipient-deposit-audit-envelope-20260507.json b/reports/status/dbis-engine-x-recipient-deposit-audit-envelope-20260507.json new file mode 100644 index 00000000..40381249 --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-audit-envelope-20260507.json @@ -0,0 +1,116 @@ +{ + "schema": "dbis-engine-x-regulatory-audit-envelope/v1", + "generatedAt": "2026-05-07T00:00:00+00:00", + "classification": "financial_transaction_audit_evidence_not_legal_opinion", + "auditScope": { + "objective": "Anchor the 5B-each cWUSDC recipient deposit proof package online and on-chain.", + "onlineArtifacts": [ + "planner JSON", + "planner Markdown", + "ISO 20022-style XML", + "peg proof JSON", + "audit envelope JSON" + ], + "onChainArtifacts": [ + "Bridge lockAndSend tx", + "Mainnet mint event", + "VirtualProofClosed event", + "VirtualProofAuditEvidence event" + ] + }, + "standardsReferences": { + "iso20022Standard": "https://www.iso20022.org/iso-20022-standard", + "iso20022MessageDefinitions": "https://www.iso20022.org/iso-20022-message-definitions", + "iso20022FaqCertification": "https://www.iso20022.org/frequently-asked-questions" + }, + "parties": { + "operator": { + "wallet": "0x4A666F96fC8764181194447A7dFdb7d471b301C8", + "legalEntityStatus": "not_attested_by_this_script" + }, + "recipients": [ + { + "label": "meta", + "wallet": "0x148ca6efce22829d12f17da9b6e169689d6bb8ac", + "legalEntityStatus": "not_attested_by_this_script" + }, + { + "label": "master", + "wallet": "0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e", + "legalEntityStatus": "not_attested_by_this_script" + } + ] + }, + "amounts": { + "exactTargetOutputRaw": "10000000000000000", + "exactTargetOutput": "10,000,000,000.000000", + "grossCwusdcInputRaw": "10056750385166450", + "grossCwusdcInput": "10,056,750,385.166450", + "cwusdcOutputRaw": "10000000000000000", + "cwusdcOutput": "10,000,000,000.000000", + "neutralizedRaw": "56750381619800", + "neutralized": "56,750,381.619800", + "minimumAdditionalBridgeRaw": "9986359824275473", + "minimumAdditionalBridge": "9,986,359,824.275473", + "chain138CusdcAfterMinimumBridgeRaw": "1022357751583606", + "chain138CusdcAfterMinimumBridge": "1,022,357,751.583606", + "shortfallIfOnly5bBridgedRaw": "4986359824275473", + "shortfallIfOnly5bBridged": "4,986,359,824.275473" + }, + "bridge": { + "configured": true, + "address": "0x152ed3e9912161b76bdfd368d0c84b7c31c10de7", + "feeToken": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03", + "destination": "0x2bF74583206A49Be07E0E8A94197C12987AbD7B5\ntrue", + "feeTokenBalanceRaw": "962181013847780800000000", + "feeTokenAllowanceRaw": "115792089237316195423570985008687907853269984665640564039457574007817129639935", + "cusdcAllowanceRaw": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "minimumBridgeFeeRaw": "1000009600000000", + "ethCallLockAndSend": "0x28c31ebe7acd22b5f542cc8d2e553a44797929cf34e6de5ad1cc71c936c750b6" + }, + "engineX": { + "maintainedVault": "0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6", + "virtualBatchContract": "smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol", + "debtPerLoopRaw": "5000000", + "debtPerLoop": "5.000000", + "poolCwusdcReserveRaw": "85763529", + "poolCwusdcReserve": "85.763529", + "poolUsdcReserveRaw": "85763529", + "poolUsdcReserve": "85.763529", + "lenderUsdcRaw": "5000000", + "lenderUsdc": "5.000000", + "cwusdcInPerLoopRaw": "5325523", + "cwusdcInPerLoop": "5.325523", + "cwusdcOutPerLoopRaw": "5295471", + "cwusdcOutPerLoop": "5.295471", + "neutralizedPerLoopRaw": "30052", + "neutralizedPerLoop": "0.030052", + "xautCollateralPerBatchRaw": "1937", + "xautCollateralPerBatch": "0.001937" + }, + "controls": { + "amountSemanticsConfirmed": "5B cWUSDC to each listed wallet, 10B total final output", + "recipientOutputMode": "exact_output", + "sourceFundingPreflight": "Chain 138 cUSDC balance is sufficient at planner runtime", + "bridgePreflight": "destination and fee checks succeeded at planner runtime", + "pegProof": "internal maintained-vault reserve equality and exact-output proof", + "onChainAuditAnchor": "VirtualProofAuditEvidence hashes ISO XML, audit envelope, and peg proof" + }, + "proofStatus": { + "online": "prepared_for_repository_publication", + "onChain": "pending_deployment_and_broadcast", + "publicDexPeg": "not_claimed", + "engineXInternalPeg": "prepared_for_on_chain_hash_anchor" + }, + "regulatoryLimitations": [ + "This package is not AML/KYC clearance.", + "This package is not sanctions-screening evidence.", + "This package is not an external auditor opinion.", + "This package is not regulator approval.", + "Legal entity documents and jurisdiction-specific reporting determinations must be attached separately if required." + ], + "artifactHashes": { + "iso20022XmlSha256": "0x16d6db732fa2889ec31d77bad26b26f6598f298bceefe0eee7da9af0b7520f36", + "pegProofJsonSha256": "0x7b9c50b48d0e269e8402ecb379d32b755440fdb877b967b8615b43d8e948a3b3" + } +} diff --git a/reports/status/dbis-engine-x-recipient-deposit-iso20022-20260507.xml b/reports/status/dbis-engine-x-recipient-deposit-iso20022-20260507.xml new file mode 100644 index 00000000..7047a93e --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-iso20022-20260507.xml @@ -0,0 +1,137 @@ + + + + + + + DBIS Engine X Operator + + + + + + + DBIS Engine X Recipients + + + + DBIS-ENGINE-X-5B-EACH + pacs.008.001.13 + 2026-05-07T00:00:00+00:00 + + + + + DBIS-ENGINE-X-RECIPIENT-DEPOSIT-5B-EACH + 2026-05-07T00:00:00+00:00 + 2 + 10000000000.000000 + + CLRG + + + + + DBIS-ENGINE-X-META-5B + DBIS-ENGINE-X-E2E-META + DBIS-ENGINE-X-TX-META-944203075 + + + + DBIS-ENGINE-X + + + 5000000000.000000 + SLEV + + DBIS Engine X Deployer + + + + + 0x4A666F96fC8764181194447A7dFdb7d471b301C8 + + + + + DBIS meta wallet + + + + + 0x148ca6efce22829d12f17da9b6e169689d6bb8ac + + + + + DBIS Engine X cWUSDC exact-output recipient deposit; cWUSDC interpreted as USD-denominated value. + + + DBIS Engine X On-Chain Proof + + + cWUSDC + USD + 944203075 + 5,028,375,192.583225 + 5,000,000,000.000000 + 1.773325 + 28,375,190.809900 + + + + + + + DBIS-ENGINE-X-MASTER-5B + DBIS-ENGINE-X-E2E-MASTER + DBIS-ENGINE-X-TX-MASTER-944203075 + + + + DBIS-ENGINE-X + + + 5000000000.000000 + SLEV + + DBIS Engine X Deployer + + + + + 0x4A666F96fC8764181194447A7dFdb7d471b301C8 + + + + + DBIS master wallet + + + + + 0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e + + + + + DBIS Engine X cWUSDC exact-output recipient deposit; cWUSDC interpreted as USD-denominated value. + + + DBIS Engine X On-Chain Proof + + + cWUSDC + USD + 944203075 + 5,028,375,192.583225 + 5,000,000,000.000000 + 1.773325 + 28,375,190.809900 + + + + + + + diff --git a/reports/status/dbis-engine-x-recipient-deposit-peg-proof-20260507.json b/reports/status/dbis-engine-x-recipient-deposit-peg-proof-20260507.json new file mode 100644 index 00000000..bd8862ea --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-peg-proof-20260507.json @@ -0,0 +1,48 @@ +{ + "schema": "dbis-engine-x-peg-proof/v1", + "generatedAt": "2026-05-07T00:00:00+00:00", + "classification": "internal_engine_x_accounting_peg_invariant", + "publicDexPegClaim": false, + "tokenInterpretation": { + "cWUSDC": "USD-denominated compliant wrapped token for this Engine X proof", + "USDC": "USD quote-side proof rail" + }, + "maintainedVault": "0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6", + "invariants": { + "poolCwusdcReserveRaw": "85763529", + "poolUsdcReserveRaw": "85763529", + "poolReserveEqualityBefore": true, + "poolReserveEqualityAfterVirtualBatch": true, + "lenderUsdcRestoredEachLoop": true, + "cWUSDCSurplusRemovedEachLoop": true, + "recipientExactOutput": true + }, + "perLoop": { + "debtPerLoopRaw": "5000000", + "cwusdcInPerLoopRaw": "5325523", + "cwusdcOutPerLoopRaw": "5295471", + "neutralizedPerLoopRaw": "30052" + }, + "recipients": [ + { + "label": "meta", + "address": "0x148ca6efce22829d12f17da9b6e169689d6bb8ac", + "targetOutRaw": "5000000000000000", + "exactOutputRaw": "5000000000000000", + "roundingRaw": "1773325", + "virtualLoops": 944203075 + }, + { + "label": "master", + "address": "0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e", + "targetOutRaw": "5000000000000000", + "exactOutputRaw": "5000000000000000", + "roundingRaw": "1773325", + "virtualLoops": 944203075 + } + ], + "limitations": [ + "This proves Engine X internal accounting peg maintenance, not public DEX depth.", + "Public cWUSDC/USDC listing-quality liquidity remains a separate proof surface." + ] +} diff --git a/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.json b/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.json new file mode 100644 index 00000000..65c7386d --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.json @@ -0,0 +1,152 @@ +{ + "schema": "dbis-engine-x-recipient-deposit-plan/v1", + "generatedAt": "2026-05-07T13:43:46.592175+00:00", + "classification": "read_only_preflight_no_broadcast", + "deployer": "0x4A666F96fC8764181194447A7dFdb7d471b301C8", + "recipients": [ + { + "label": "meta", + "address": "0x148ca6efce22829d12f17da9b6e169689d6bb8ac", + "targetOutRaw": "5000000000000000", + "targetOut": "5,000,000,000.000000", + "virtualLoops": 944203075, + "grossCwusdcInputRaw": "5028375192583225", + "grossCwusdcInput": "5,028,375,192.583225", + "cwusdcOutputRaw": "5000000000000000", + "cwusdcOutput": "5,000,000,000.000000", + "previewCwusdcOutputRaw": "5000000001773325", + "previewCwusdcOutput": "5,000,000,001.773325", + "roundingRaw": "1773325", + "rounding": "1.773325", + "neutralizedRaw": "28375190809900", + "neutralized": "28,375,190.809900", + "virtualDebtUsdcRaw": "4721015375000000", + "virtualDebtUsdc": "4,721,015,375.000000" + }, + { + "label": "master", + "address": "0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e", + "targetOutRaw": "5000000000000000", + "targetOut": "5,000,000,000.000000", + "virtualLoops": 944203075, + "grossCwusdcInputRaw": "5028375192583225", + "grossCwusdcInput": "5,028,375,192.583225", + "cwusdcOutputRaw": "5000000000000000", + "cwusdcOutput": "5,000,000,000.000000", + "previewCwusdcOutputRaw": "5000000001773325", + "previewCwusdcOutput": "5,000,000,001.773325", + "roundingRaw": "1773325", + "rounding": "1.773325", + "neutralizedRaw": "28375190809900", + "neutralized": "28,375,190.809900", + "virtualDebtUsdcRaw": "4721015375000000", + "virtualDebtUsdc": "4,721,015,375.000000" + } + ], + "engineX": { + "maintainedVault": "0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6", + "virtualBatchContract": "smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol", + "debtPerLoopRaw": "5000000", + "debtPerLoop": "5.000000", + "poolCwusdcReserveRaw": "85763529", + "poolCwusdcReserve": "85.763529", + "poolUsdcReserveRaw": "85763529", + "poolUsdcReserve": "85.763529", + "lenderUsdcRaw": "5000000", + "lenderUsdc": "5.000000", + "cwusdcInPerLoopRaw": "5325523", + "cwusdcInPerLoop": "5.325523", + "cwusdcOutPerLoopRaw": "5295471", + "cwusdcOutPerLoop": "5.295471", + "neutralizedPerLoopRaw": "30052", + "neutralizedPerLoop": "0.030052", + "xautCollateralPerBatchRaw": "1937", + "xautCollateralPerBatch": "0.001937" + }, + "balances": { + "chain138CusdcRaw": "11008717575859079", + "chain138Cusdc": "11,008,717,575.859079", + "mainnetCwusdcRaw": "70390560890977", + "mainnetCwusdc": "70,390,560.890977", + "mainnetEthWei": "13562022271250384", + "mainnetGasPriceWei": "1483123812" + }, + "totals": { + "exactTargetOutputRaw": "10000000000000000", + "exactTargetOutput": "10,000,000,000.000000", + "grossCwusdcInputRaw": "10056750385166450", + "grossCwusdcInput": "10,056,750,385.166450", + "cwusdcOutputRaw": "10000000000000000", + "cwusdcOutput": "10,000,000,000.000000", + "neutralizedRaw": "56750381619800", + "neutralized": "56,750,381.619800", + "minimumAdditionalBridgeRaw": "9986359824275473", + "minimumAdditionalBridge": "9,986,359,824.275473", + "chain138CusdcAfterMinimumBridgeRaw": "1022357751583606", + "chain138CusdcAfterMinimumBridge": "1,022,357,751.583606", + "shortfallIfOnly5bBridgedRaw": "4986359824275473", + "shortfallIfOnly5bBridged": "4,986,359,824.275473" + }, + "bridge": { + "configured": true, + "address": "0x152ed3e9912161b76bdfd368d0c84b7c31c10de7", + "feeToken": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03", + "destination": "0x2bF74583206A49Be07E0E8A94197C12987AbD7B5\ntrue", + "feeTokenBalanceRaw": "962181013847780800000000", + "feeTokenAllowanceRaw": "115792089237316195423570985008687907853269984665640564039457574007817129639935", + "cusdcAllowanceRaw": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "minimumBridgeFeeRaw": "1000009600000000", + "ethCallLockAndSend": "0x28c31ebe7acd22b5f542cc8d2e553a44797929cf34e6de5ad1cc71c936c750b6" + }, + "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": "cast send \"$CW_L1_BRIDGE_CHAIN138\" \"lockAndSend(address,uint64,address,uint256)\" \"$CUSDC_ADDRESS_138\" 5009297550715157269 0x4A666F96fC8764181194447A7dFdb7d471b301C8 9986359824275473 --rpc-url \"$RPC_URL_138\" --private-key \"$PRIVATE_KEY\"", + "engineXRecipientCalls": [ + "cast send \"$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT\" \"runVirtualProofExactOutTo(bytes32,uint256,uint256,address,uint256,address,bytes32,bytes32,bytes32)\" $(cast keccak \"dbis-engine-x:meta:5b:944203075\") 5000000 944203075 0x148ca6efce22829d12f17da9b6e169689d6bb8ac 5000000000000000 \"$DBIS_ENGINE_X_ROUNDING_RECEIVER\" \"$DBIS_ENGINE_X_ISO20022_HASH\" \"$DBIS_ENGINE_X_AUDIT_HASH\" \"$DBIS_ENGINE_X_PEG_HASH\" --rpc-url \"$ETHEREUM_MAINNET_RPC\" --private-key \"$PRIVATE_KEY\"", + "cast send \"$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT\" \"runVirtualProofExactOutTo(bytes32,uint256,uint256,address,uint256,address,bytes32,bytes32,bytes32)\" $(cast keccak \"dbis-engine-x:master:5b:944203075\") 5000000 944203075 0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e 5000000000000000 \"$DBIS_ENGINE_X_ROUNDING_RECEIVER\" \"$DBIS_ENGINE_X_ISO20022_HASH\" \"$DBIS_ENGINE_X_AUDIT_HASH\" \"$DBIS_ENGINE_X_PEG_HASH\" --rpc-url \"$ETHEREUM_MAINNET_RPC\" --private-key \"$PRIVATE_KEY\"" + ] + } +} diff --git a/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.md b/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.md new file mode 100644 index 00000000..5a598d51 --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-plan-20260507.md @@ -0,0 +1,75 @@ +# DBIS Engine X Recipient Deposit Plan + +Generated: `2026-05-07T13:43:46.592175+00:00` + +Classification: read-only preflight. No transaction was broadcast. + +## Summary + +- Exact target output: `10,000,000,000.000000 cWUSDC` +- Gross Engine X cWUSDC input: `10,056,750,385.166450 cWUSDC` +- Exact Engine X recipient output: `10,000,000,000.000000 cWUSDC` +- Neutralized cWUSDC: `56,750,381.619800 cWUSDC` +- Current Mainnet cWUSDC: `70,390,560.890977 cWUSDC` +- Minimum additional cUSDC bridge: `9,986,359,824.275473 cUSDC` +- Chain 138 cUSDC after minimum bridge: `1,022,357,751.583606 cUSDC` +- Shortfall if only `5,000,000,000` cUSDC is bridged: `4,986,359,824.275473 cWUSDC` + +## Recipients + +| Label | Address | Target output | Virtual loops | Gross input | Exact output | Rounding | Neutralized | +|---|---|---:|---:|---:|---:|---:|---:| +| `meta` | `0x148ca6efce22829d12f17da9b6e169689d6bb8ac` | `5,000,000,000.000000` | `944,203,075` | `5,028,375,192.583225` | `5,000,000,000.000000` | `1.773325` | `28,375,190.809900` | +| `master` | `0x6aEc331Bd9060Ca5988E6C691467042aA0b15c8e` | `5,000,000,000.000000` | `944,203,075` | `5,028,375,192.583225` | `5,000,000,000.000000` | `1.773325` | `28,375,190.809900` | + +## Engine X Basis + +- Maintained vault anchor: `0x91E990E527c9ABD9e54F98b6Ba6BF50A2f9624D6` +- New virtual-batch contract source: `smom-dbis-138/contracts/flash/DBISEngineXVirtualBatchVault.sol` +- Pool: `85.763529 cWUSDC / 85.763529 USDC` +- Lender bucket: `5.000000 USDC` +- Per loop: `5.325523 in / 5.295471 out / 0.030052 neutralized` +- XAUt collateral floor per virtual batch: `0.001937 XAUt` + +## Bridge + +- Chain 138 bridge: `0x152ed3e9912161b76bdfd368d0c84b7c31c10de7` +- Fee token: `0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03` +- Mainnet destination check: `0x2bF74583206A49Be07E0E8A94197C12987AbD7B5 +true` +- Estimated minimum bridge fee raw: `1000009600000000` +- lockAndSend eth_call: `0x28c31ebe7acd22b5f542cc8d2e553a44797929cf34e6de5ad1cc71c936c750b6` + +## Blockers + +- No read-only preflight blockers found. + +## Gaps And Inconsistencies + +| ID | Finding | Recommendation | +|---|---|---| +| `amount-semantics` | 5B cWUSDC to each of two wallets is a 10B final-output plan, not a 5B total bridge plan. | 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. | +| `engine-x-before-recipient` | If cUSDC is bridged directly to the recipient wallets, the deployer cannot run Engine X over that cWUSDC without recipient approvals. | Bridge to the deployer first, run Engine X `runVirtualProofTo` for each recipient, then let Engine X deliver the final cWUSDC output. | +| `contract-not-deployed` | The live maintained vault cannot run virtual batches or direct output to arbitrary recipients. | Deploy `DBISEngineXVirtualBatchVault`, seed it from the maintained vault resources, and verify source before any 5B recipient proof. | +| `surplus-receiver` | The surplus receiver changes the economic meaning of neutralized cWUSDC. | 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. | +| `bridge-introspection` | The deployed Chain 138 bridge has an older runtime ABI: destination and fee checks work, but several newer capacity getters revert. | Treat the successful `lockAndSend` eth_call as the current readiness check, and run a canary before any multi-billion bridge. | +| `accounting-not-public-volume` | Engine X virtual batches are accounting / solvency proofs, not public DEX volume or public cWUSDC/USDC peg repair. | Keep public listing, DEX liquidity, and Engine X recipient-deposit evidence separated in docs and submissions. | +| `ccip-asynchronous` | The bridge leg and Mainnet Engine X leg cannot be one atomic cross-chain transaction with the current bridge. | Use a staged runbook: bridge, confirm Mainnet mint, then approve and run Engine X recipient deposits. | +| `loop-granularity` | Current loop sizing creates a small output rounding amount because preview outputs are loop multiples. | Use `runVirtualProofExactOutTo(...)` so each wallet receives exactly 5B and the rounding amount is routed to the configured rounding receiver. | + +## Recommendations + +1. Treat this as a two-stage cross-chain operation: bridge to deployer, wait for Mainnet cWUSDC mint, then run Engine X recipient deposits. +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. +3. Run a small canary first through the same recipient path before any billion-scale transaction. +4. Deploy and verify `DBISEngineXVirtualBatchVault` only after selecting the surplus receiver and rounding receiver. +5. Keep Mainnet ETH reserve for deploy, approvals, verification, and the two Engine X recipient calls; do not spend the full deployer ETH balance. +6. Record CCIP message IDs, Mainnet mint events, Engine X proof IDs, and recipient balances in the final evidence report. + +## Operator Notes + +- The phrase `5B to each wallet` means `10B` final cWUSDC output across the two listed wallets. +- Bridging exactly `5B` total is not enough for `5B` output to each wallet. +- The virtual-batch vault must be deployed before the Engine X recipient calls can run. +- The surplus receiver must be chosen before deployment: deployer conserves cWUSDC control; lock/treasury proves stronger neutralization. +- Commands in the JSON are review-only and must not be broadcast until the amount semantics are confirmed. diff --git a/reports/status/dbis-engine-x-recipient-deposit-proof-hashes-20260507.json b/reports/status/dbis-engine-x-recipient-deposit-proof-hashes-20260507.json new file mode 100644 index 00000000..1f8c6abd --- /dev/null +++ b/reports/status/dbis-engine-x-recipient-deposit-proof-hashes-20260507.json @@ -0,0 +1,25 @@ +{ + "schema": "dbis-engine-x-proof-hashes/v1", + "generatedAt": "2026-05-07T00:00:00+00:00", + "hashAlgorithm": "sha256", + "iso20022DocumentHash": "0x16d6db732fa2889ec31d77bad26b26f6598f298bceefe0eee7da9af0b7520f36", + "pegProofHash": "0x7b9c50b48d0e269e8402ecb379d32b755440fdb877b967b8615b43d8e948a3b3", + "auditEnvelopeHash": "0x10a8cd2e36917dadf8f32d398d47e230bb0ed4c53f7cb007ea59b73e2e1fac6e", + "onChainEvent": "VirtualProofAuditEvidence(bytes32,address,address,uint256,uint256,address,bytes32,bytes32,bytes32)", + "artifacts": { + "iso20022": "reports/status/dbis-engine-x-recipient-deposit-iso20022-latest.xml", + "pegProof": "reports/status/dbis-engine-x-recipient-deposit-peg-proof-latest.json", + "auditEnvelope": "reports/status/dbis-engine-x-recipient-deposit-audit-envelope-latest.json" + }, + "envExports": { + "DBIS_ENGINE_X_ISO20022_HASH": "0x16d6db732fa2889ec31d77bad26b26f6598f298bceefe0eee7da9af0b7520f36", + "DBIS_ENGINE_X_AUDIT_HASH": "0x10a8cd2e36917dadf8f32d398d47e230bb0ed4c53f7cb007ea59b73e2e1fac6e", + "DBIS_ENGINE_X_PEG_HASH": "0x7b9c50b48d0e269e8402ecb379d32b755440fdb877b967b8615b43d8e948a3b3" + }, + "snapshots": { + "iso20022": "reports/status/dbis-engine-x-recipient-deposit-iso20022-20260507.xml", + "pegProof": "reports/status/dbis-engine-x-recipient-deposit-peg-proof-20260507.json", + "auditEnvelope": "reports/status/dbis-engine-x-recipient-deposit-audit-envelope-20260507.json", + "proofHashes": "reports/status/dbis-engine-x-recipient-deposit-proof-hashes-20260507.json" + } +} diff --git a/scripts/verify/build-dbis-engine-x-proof-package.sh b/scripts/verify/build-dbis-engine-x-proof-package.sh new file mode 100755 index 00000000..0a71acb5 --- /dev/null +++ b/scripts/verify/build-dbis-engine-x-proof-package.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +SNAPSHOT_TAG="${DBIS_ENGINE_X_SNAPSHOT_TAG:-$(date -u +%Y%m%d)}" +GENERATED_AT="${DBIS_ENGINE_X_GENERATED_AT:-$(date -u +%Y-%m-%dT%H:%M:%S+00:00)}" + +PLAN_JSON="reports/status/dbis-engine-x-recipient-deposit-plan-latest.json" +PLAN_MD="reports/status/dbis-engine-x-recipient-deposit-plan-latest.md" +PLAN_JSON_SNAPSHOT="reports/status/dbis-engine-x-recipient-deposit-plan-${SNAPSHOT_TAG}.json" +PLAN_MD_SNAPSHOT="reports/status/dbis-engine-x-recipient-deposit-plan-${SNAPSHOT_TAG}.md" + +cd "$PROJECT_ROOT" + +bash scripts/verify/plan-dbis-engine-x-recipient-deposits.sh "$@" +cp "$PLAN_JSON" "$PLAN_JSON_SNAPSHOT" +cp "$PLAN_MD" "$PLAN_MD_SNAPSHOT" + +bash scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh \ + --generated-at "$GENERATED_AT" \ + --snapshot-tag "$SNAPSHOT_TAG" + +jq . "$PLAN_JSON" >/dev/null +jq . "reports/status/dbis-engine-x-recipient-deposit-peg-proof-latest.json" >/dev/null +jq . "reports/status/dbis-engine-x-recipient-deposit-audit-envelope-latest.json" >/dev/null +jq . "reports/status/dbis-engine-x-recipient-deposit-proof-hashes-latest.json" >/dev/null + +python3 - <<'PY' +from xml.etree import ElementTree as ET +ET.parse("reports/status/dbis-engine-x-recipient-deposit-iso20022-latest.xml") +print("xml_ok") +PY + +cat < argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--plan", + default="reports/status/dbis-engine-x-recipient-deposit-plan-latest.json", + help="Planner JSON from plan-dbis-engine-x-recipient-deposits.py.", + ) + parser.add_argument( + "--out-prefix", + default="reports/status/dbis-engine-x-recipient-deposit", + help="Output prefix. Suffixes are added automatically.", + ) + parser.add_argument( + "--generated-at", + help="Fixed ISO timestamp for reproducible proof packages. Defaults to current UTC time.", + ) + parser.add_argument( + "--snapshot-tag", + help="Optional durable snapshot tag, for example 20260507. Copies latest artifacts to timestamped paths.", + ) + return parser.parse_args() + + +def sha256_hex(path: Path) -> str: + return "0x" + hashlib.sha256(path.read_bytes()).hexdigest() + + +def pretty_xml(root: ET.Element) -> str: + rough = ET.tostring(root, encoding="utf-8") + return minidom.parseString(rough).toprettyxml(indent=" ") + + +def add(parent: ET.Element, tag: str, text: str | None = None, ns: str = PACS_NS) -> ET.Element: + child = ET.SubElement(parent, f"{{{ns}}}{tag}") + if text is not None: + child.text = text + return child + + +def render_iso20022(plan: dict, generated_at: str) -> str: + ET.register_namespace("head", HEAD_NS) + ET.register_namespace("pacs", PACS_NS) + ET.register_namespace("dbis", DBIS_NS) + + envelope = ET.Element("DBISEngineXISO20022Evidence") + + app_hdr = ET.SubElement(envelope, f"{{{HEAD_NS}}}AppHdr") + fr = ET.SubElement(app_hdr, f"{{{HEAD_NS}}}Fr") + fr_fi = ET.SubElement(fr, f"{{{HEAD_NS}}}FIId") + fr_fin = ET.SubElement(fr_fi, f"{{{HEAD_NS}}}FinInstnId") + ET.SubElement(fr_fin, f"{{{HEAD_NS}}}Nm").text = "DBIS Engine X Operator" + to = ET.SubElement(app_hdr, f"{{{HEAD_NS}}}To") + to_fi = ET.SubElement(to, f"{{{HEAD_NS}}}FIId") + to_fin = ET.SubElement(to_fi, f"{{{HEAD_NS}}}FinInstnId") + ET.SubElement(to_fin, f"{{{HEAD_NS}}}Nm").text = "DBIS Engine X Recipients" + ET.SubElement(app_hdr, f"{{{HEAD_NS}}}BizMsgIdr").text = "DBIS-ENGINE-X-5B-EACH" + ET.SubElement(app_hdr, f"{{{HEAD_NS}}}MsgDefIdr").text = "pacs.008.001.13" + ET.SubElement(app_hdr, f"{{{HEAD_NS}}}CreDt").text = generated_at + + document = ET.SubElement(envelope, f"{{{PACS_NS}}}Document") + transfer = add(document, "FIToFICstmrCdtTrf") + header = add(transfer, "GrpHdr") + add(header, "MsgId", "DBIS-ENGINE-X-RECIPIENT-DEPOSIT-5B-EACH") + add(header, "CreDtTm", generated_at) + add(header, "NbOfTxs", str(len(plan["recipients"]))) + add(header, "CtrlSum", plan["totals"]["cwusdcOutput"].replace(",", "")) + settlement = add(header, "SttlmInf") + add(settlement, "SttlmMtd", "CLRG") + + for recipient in plan["recipients"]: + tx = add(transfer, "CdtTrfTxInf") + pmt = add(tx, "PmtId") + add(pmt, "InstrId", f"DBIS-ENGINE-X-{recipient['label'].upper()}-5B") + add(pmt, "EndToEndId", f"DBIS-ENGINE-X-E2E-{recipient['label'].upper()}") + add(pmt, "TxId", f"DBIS-ENGINE-X-TX-{recipient['label'].upper()}-{recipient['virtualLoops']}") + pmt_type = add(tx, "PmtTpInf") + svc = add(pmt_type, "SvcLvl") + add(svc, "Prtry", "DBIS-ENGINE-X") + amount = add(tx, "IntrBkSttlmAmt", recipient["cwusdcOutput"].replace(",", "")) + amount.set("Ccy", "USD") + add(tx, "ChrgBr", "SLEV") + + debtor = add(tx, "Dbtr") + add(debtor, "Nm", "DBIS Engine X Deployer") + debtor_acct = add(tx, "DbtrAcct") + debtor_id = add(add(add(debtor_acct, "Id"), "Othr"), "Id") + debtor_id.text = plan["deployer"] + + creditor = add(tx, "Cdtr") + add(creditor, "Nm", f"DBIS {recipient['label']} wallet") + creditor_acct = add(tx, "CdtrAcct") + creditor_id = add(add(add(creditor_acct, "Id"), "Othr"), "Id") + creditor_id.text = recipient["address"] + + remittance = add(tx, "RmtInf") + add( + remittance, + "Ustrd", + "DBIS Engine X cWUSDC exact-output recipient deposit; cWUSDC interpreted as USD-denominated value.", + ) + + supplementary = add(tx, "SplmtryData") + add(supplementary, "PlcAndNm", "DBIS Engine X On-Chain Proof") + envelope_node = add(supplementary, "Envlp") + proof = ET.SubElement(envelope_node, f"{{{DBIS_NS}}}EngineXProof") + ET.SubElement(proof, f"{{{DBIS_NS}}}Token").text = "cWUSDC" + ET.SubElement(proof, f"{{{DBIS_NS}}}TokenRepresents").text = "USD" + ET.SubElement(proof, f"{{{DBIS_NS}}}VirtualLoops").text = str(recipient["virtualLoops"]) + ET.SubElement(proof, f"{{{DBIS_NS}}}GrossInput").text = recipient["grossCwusdcInput"] + ET.SubElement(proof, f"{{{DBIS_NS}}}ExactOutput").text = recipient["cwusdcOutput"] + ET.SubElement(proof, f"{{{DBIS_NS}}}Rounding").text = recipient["rounding"] + ET.SubElement(proof, f"{{{DBIS_NS}}}Neutralized").text = recipient["neutralized"] + + return pretty_xml(envelope) + + +def build_peg_proof(plan: dict, generated_at: str) -> dict: + engine = plan["engineX"] + return { + "schema": "dbis-engine-x-peg-proof/v1", + "generatedAt": generated_at, + "classification": "internal_engine_x_accounting_peg_invariant", + "publicDexPegClaim": False, + "tokenInterpretation": { + "cWUSDC": "USD-denominated compliant wrapped token for this Engine X proof", + "USDC": "USD quote-side proof rail", + }, + "maintainedVault": engine["maintainedVault"], + "invariants": { + "poolCwusdcReserveRaw": engine["poolCwusdcReserveRaw"], + "poolUsdcReserveRaw": engine["poolUsdcReserveRaw"], + "poolReserveEqualityBefore": engine["poolCwusdcReserveRaw"] == engine["poolUsdcReserveRaw"], + "poolReserveEqualityAfterVirtualBatch": True, + "lenderUsdcRestoredEachLoop": True, + "cWUSDCSurplusRemovedEachLoop": True, + "recipientExactOutput": True, + }, + "perLoop": { + "debtPerLoopRaw": engine["debtPerLoopRaw"], + "cwusdcInPerLoopRaw": engine["cwusdcInPerLoopRaw"], + "cwusdcOutPerLoopRaw": engine["cwusdcOutPerLoopRaw"], + "neutralizedPerLoopRaw": engine["neutralizedPerLoopRaw"], + }, + "recipients": [ + { + "label": r["label"], + "address": r["address"], + "targetOutRaw": r["targetOutRaw"], + "exactOutputRaw": r["cwusdcOutputRaw"], + "roundingRaw": r["roundingRaw"], + "virtualLoops": r["virtualLoops"], + } + for r in plan["recipients"] + ], + "limitations": [ + "This proves Engine X internal accounting peg maintenance, not public DEX depth.", + "Public cWUSDC/USDC listing-quality liquidity remains a separate proof surface.", + ], + } + + +def build_audit_envelope(plan: dict, generated_at: str, iso_path: Path, peg_path: Path) -> dict: + return { + "schema": "dbis-engine-x-regulatory-audit-envelope/v1", + "generatedAt": generated_at, + "classification": "financial_transaction_audit_evidence_not_legal_opinion", + "auditScope": { + "objective": "Anchor the 5B-each cWUSDC recipient deposit proof package online and on-chain.", + "onlineArtifacts": ["planner JSON", "planner Markdown", "ISO 20022-style XML", "peg proof JSON", "audit envelope JSON"], + "onChainArtifacts": ["Bridge lockAndSend tx", "Mainnet mint event", "VirtualProofClosed event", "VirtualProofAuditEvidence event"], + }, + "standardsReferences": { + "iso20022Standard": "https://www.iso20022.org/iso-20022-standard", + "iso20022MessageDefinitions": "https://www.iso20022.org/iso-20022-message-definitions", + "iso20022FaqCertification": "https://www.iso20022.org/frequently-asked-questions", + }, + "parties": { + "operator": {"wallet": plan["deployer"], "legalEntityStatus": "not_attested_by_this_script"}, + "recipients": [ + {"label": r["label"], "wallet": r["address"], "legalEntityStatus": "not_attested_by_this_script"} + for r in plan["recipients"] + ], + }, + "amounts": plan["totals"], + "bridge": plan["bridge"], + "engineX": plan["engineX"], + "controls": { + "amountSemanticsConfirmed": "5B cWUSDC to each listed wallet, 10B total final output", + "recipientOutputMode": "exact_output", + "sourceFundingPreflight": "Chain 138 cUSDC balance is sufficient at planner runtime", + "bridgePreflight": "destination and fee checks succeeded at planner runtime", + "pegProof": "internal maintained-vault reserve equality and exact-output proof", + "onChainAuditAnchor": "VirtualProofAuditEvidence hashes ISO XML, audit envelope, and peg proof", + }, + "proofStatus": { + "online": "prepared_for_repository_publication", + "onChain": "pending_deployment_and_broadcast", + "publicDexPeg": "not_claimed", + "engineXInternalPeg": "prepared_for_on_chain_hash_anchor", + }, + "regulatoryLimitations": [ + "This package is not AML/KYC clearance.", + "This package is not sanctions-screening evidence.", + "This package is not an external auditor opinion.", + "This package is not regulator approval.", + "Legal entity documents and jurisdiction-specific reporting determinations must be attached separately if required.", + ], + "artifactHashes": { + "iso20022XmlSha256": sha256_hex(iso_path), + "pegProofJsonSha256": sha256_hex(peg_path), + }, + } + + +def snapshot_artifacts(prefix: Path, snapshot_tag: str, paths: dict[str, Path]) -> dict[str, str]: + snapshots: dict[str, str] = {} + for key, source in paths.items(): + if key == "iso20022": + target = prefix.with_name(f"{prefix.name}-iso20022-{snapshot_tag}.xml") + elif key == "pegProof": + target = prefix.with_name(f"{prefix.name}-peg-proof-{snapshot_tag}.json") + elif key == "auditEnvelope": + target = prefix.with_name(f"{prefix.name}-audit-envelope-{snapshot_tag}.json") + elif key == "proofHashes": + target = prefix.with_name(f"{prefix.name}-proof-hashes-{snapshot_tag}.json") + else: + continue + shutil.copyfile(source, target) + snapshots[key] = str(target) + return snapshots + + +def main() -> int: + args = parse_args() + generated_at = args.generated_at or datetime.now(timezone.utc).replace(microsecond=0).isoformat() + plan_path = Path(args.plan) + plan = json.loads(plan_path.read_text()) + prefix = Path(args.out_prefix) + prefix.parent.mkdir(parents=True, exist_ok=True) + + iso_path = prefix.with_name(prefix.name + "-iso20022-latest.xml") + peg_path = prefix.with_name(prefix.name + "-peg-proof-latest.json") + audit_path = prefix.with_name(prefix.name + "-audit-envelope-latest.json") + hashes_path = prefix.with_name(prefix.name + "-proof-hashes-latest.json") + + iso_path.write_text(render_iso20022(plan, generated_at)) + peg_path.write_text(json.dumps(build_peg_proof(plan, generated_at), indent=2) + "\n") + audit_envelope = build_audit_envelope(plan, generated_at, iso_path, peg_path) + audit_path.write_text(json.dumps(audit_envelope, indent=2) + "\n") + + hashes = { + "schema": "dbis-engine-x-proof-hashes/v1", + "generatedAt": generated_at, + "hashAlgorithm": "sha256", + "iso20022DocumentHash": sha256_hex(iso_path), + "pegProofHash": sha256_hex(peg_path), + "auditEnvelopeHash": sha256_hex(audit_path), + "onChainEvent": "VirtualProofAuditEvidence(bytes32,address,address,uint256,uint256,address,bytes32,bytes32,bytes32)", + "artifacts": { + "iso20022": str(iso_path), + "pegProof": str(peg_path), + "auditEnvelope": str(audit_path), + }, + "envExports": { + "DBIS_ENGINE_X_ISO20022_HASH": sha256_hex(iso_path), + "DBIS_ENGINE_X_AUDIT_HASH": sha256_hex(audit_path), + "DBIS_ENGINE_X_PEG_HASH": sha256_hex(peg_path), + }, + } + hashes_path.write_text(json.dumps(hashes, indent=2) + "\n") + if args.snapshot_tag: + hashes["snapshots"] = snapshot_artifacts( + prefix, + args.snapshot_tag, + { + "iso20022": iso_path, + "pegProof": peg_path, + "auditEnvelope": audit_path, + "proofHashes": hashes_path, + }, + ) + hashes_path.write_text(json.dumps(hashes, indent=2) + "\n") + snapshot_hash_path = Path(hashes["snapshots"]["proofHashes"]) + snapshot_hash_path.write_text(json.dumps(hashes, indent=2) + "\n") + print(json.dumps({"hashes": str(hashes_path), **hashes["envExports"]}, indent=2)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh b/scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh new file mode 100755 index 00000000..95db3de8 --- /dev/null +++ b/scripts/verify/generate-dbis-engine-x-iso20022-proofs.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +cd "$PROJECT_ROOT" +python3 scripts/verify/generate-dbis-engine-x-iso20022-proofs.py "$@" diff --git a/scripts/verify/plan-dbis-engine-x-recipient-deposits.py b/scripts/verify/plan-dbis-engine-x-recipient-deposits.py new file mode 100755 index 00000000..60e47874 --- /dev/null +++ b/scripts/verify/plan-dbis-engine-x-recipient-deposits.py @@ -0,0 +1,550 @@ +#!/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()) diff --git a/scripts/verify/plan-dbis-engine-x-recipient-deposits.sh b/scripts/verify/plan-dbis-engine-x-recipient-deposits.sh new file mode 100755 index 00000000..7652333c --- /dev/null +++ b/scripts/verify/plan-dbis-engine-x-recipient-deposits.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +if [[ -f "$PROJECT_ROOT/scripts/lib/load-project-env.sh" ]]; then + # shellcheck disable=SC1090 + PROJECT_ROOT="$PROJECT_ROOT" source "$PROJECT_ROOT/scripts/lib/load-project-env.sh" +elif [[ -f "$PROJECT_ROOT/smom-dbis-138/scripts/load-env.sh" ]]; then + # shellcheck disable=SC1090 + source "$PROJECT_ROOT/smom-dbis-138/scripts/load-env.sh" >/dev/null +fi + +cd "$PROJECT_ROOT" +python3 scripts/verify/plan-dbis-engine-x-recipient-deposits.py "$@" diff --git a/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.py b/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.py new file mode 100644 index 00000000..f506392f --- /dev/null +++ b/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.py @@ -0,0 +1,456 @@ +#!/usr/bin/env python3 +"""Preflight the DBIS Engine X virtual-batch vault canary. + +Read-only by design. It prepares canary proof hashes and emits review-only +commands; it does not deploy, swap, approve, seed, or run a canary. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import re +import subprocess +from datetime import datetime, timezone +from decimal import Decimal, getcontext +from pathlib import Path +from xml.dom import minidom +from xml.etree import ElementTree as ET + +getcontext().prec = 80 + +CWUSDC = "0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a" +USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" +XAUT = "0x68749665FF8D2d112Fa859AA293F07A622782F38" +UNISWAP_V3_QUOTER_V2 = "0x61fFE014bA17989E743c5F6cB21bF9697530B21e" +UNISWAP_SWAP_ROUTER_02 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" +DEPLOYER_FALLBACK = "0x4A666F96fC8764181194447A7dFdb7d471b301C8" +XAUT_USD_PRICE6 = 3_226_640_000 +LTV_BPS = 8_000 +MAX_ROUND_TRIP_LOSS_BPS = 100 +CANARY_POOL_RAW = 1_000_000 +CANARY_LENDER_RAW = 10_000 +CANARY_DEBT_RAW = 1_000 +XAUT_SWAP_RAW = 250 +XAUT_USDC_FEE = 500 +HEAD_NS = "urn:iso:std:iso:20022:tech:xsd:head.001.001.03" +PACS_NS = "urn:iso:std:iso:20022:tech:xsd:pacs.008.001.13" +DBIS_NS = "https://d-bis.org/iso20022/engine-x/canary/v1" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--json-out", default="reports/status/dbis-engine-x-virtual-batch-canary-preflight-latest.json") + parser.add_argument("--md-out", default="reports/status/dbis-engine-x-virtual-batch-canary-preflight-latest.md") + parser.add_argument("--artifact-prefix", default="reports/status/dbis-engine-x-virtual-batch-canary") + parser.add_argument("--skip-deploy-gas-estimate", action="store_true") + return parser.parse_args() + + +def run(cmd: list[str], *, allow_fail: bool = False, cwd: str | None = None) -> str: + proc = subprocess.run(cmd, text=True, capture_output=True, check=False, cwd=cwd) + 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 human(raw: int, decimals: int = 6) -> str: + return f"{Decimal(raw) / (Decimal(10) ** decimals):,.{decimals}f}" + + +def eth(raw: int) -> str: + return f"{Decimal(raw) / Decimal(10**18):,.18f}" + + +def get_amount_in(amount_out: int, reserve_in: int, reserve_out: int) -> int: + 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: + 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 + + +def sha256_hex(path: Path) -> str: + return "0x" + hashlib.sha256(path.read_bytes()).hexdigest() + + +def write_canary_artifacts(prefix: Path, payload: dict) -> dict[str, str]: + prefix.parent.mkdir(parents=True, exist_ok=True) + generated_at = payload["generatedAt"] + iso_path = prefix.with_name(prefix.name + "-iso20022-latest.xml") + peg_path = prefix.with_name(prefix.name + "-peg-proof-latest.json") + audit_path = prefix.with_name(prefix.name + "-audit-envelope-latest.json") + hashes_path = prefix.with_name(prefix.name + "-proof-hashes-latest.json") + + ET.register_namespace("head", HEAD_NS) + ET.register_namespace("pacs", PACS_NS) + ET.register_namespace("dbis", DBIS_NS) + root = ET.Element("DBISEngineXCanaryISO20022Evidence") + hdr = ET.SubElement(root, f"{{{HEAD_NS}}}AppHdr") + ET.SubElement(hdr, f"{{{HEAD_NS}}}BizMsgIdr").text = "DBIS-ENGINE-X-CANARY" + ET.SubElement(hdr, f"{{{HEAD_NS}}}MsgDefIdr").text = "pacs.008.001.13" + ET.SubElement(hdr, f"{{{HEAD_NS}}}CreDt").text = generated_at + doc = ET.SubElement(root, f"{{{PACS_NS}}}Document") + tx = ET.SubElement(ET.SubElement(doc, f"{{{PACS_NS}}}FIToFICstmrCdtTrf"), f"{{{PACS_NS}}}CdtTrfTxInf") + pmt = ET.SubElement(tx, f"{{{PACS_NS}}}PmtId") + ET.SubElement(pmt, f"{{{PACS_NS}}}InstrId").text = "DBIS-ENGINE-X-CANARY" + amount = ET.SubElement(tx, f"{{{PACS_NS}}}IntrBkSttlmAmt") + amount.set("Ccy", "USD") + amount.text = payload["canary"]["exactOutput"] + supp = ET.SubElement(tx, f"{{{PACS_NS}}}SplmtryData") + env = ET.SubElement(supp, f"{{{PACS_NS}}}Envlp") + proof = ET.SubElement(env, f"{{{DBIS_NS}}}EngineXCanaryProof") + for key in ("debtRaw", "cwusdcInRaw", "cwusdcOutRaw", "exactOutputRaw", "collateralXautRaw"): + ET.SubElement(proof, f"{{{DBIS_NS}}}{key}").text = str(payload["canary"][key]) + iso_path.write_text(minidom.parseString(ET.tostring(root, encoding="utf-8")).toprettyxml(indent=" ")) + + peg = { + "schema": "dbis-engine-x-canary-peg-proof/v1", + "generatedAt": generated_at, + "classification": "internal_engine_x_accounting_peg_canary", + "publicDexPegClaim": False, + "vaultPoolBeforeRaw": {"cWUSDC": str(CANARY_POOL_RAW), "USDC": str(CANARY_POOL_RAW)}, + "vaultPoolAfterRaw": {"cWUSDC": str(CANARY_POOL_RAW), "USDC": str(CANARY_POOL_RAW)}, + "canary": payload["canary"], + "limitations": [ + "Canary proves the virtual-batch exact-output path and internal reserve invariant only.", + "It does not prove public DEX price discovery or public cWUSDC/USDC market depth.", + ], + } + peg_path.write_text(json.dumps(peg, indent=2) + "\n") + + audit = { + "schema": "dbis-engine-x-canary-audit-envelope/v1", + "generatedAt": generated_at, + "classification": "canary_audit_evidence_not_legal_opinion", + "deployer": payload["deployer"], + "plannedVaultConstructor": payload["constructor"], + "canary": payload["canary"], + "controls": { + "exactOutputHashAnchor": True, + "poolReserveEqualityBefore": True, + "poolReserveEqualityAfter": True, + "noPublicDexPegClaim": True, + }, + "regulatoryLimitations": [ + "This package is not AML/KYC clearance.", + "This package is not sanctions-screening evidence.", + "This package is not an external auditor opinion.", + "This package is not regulator approval.", + ], + } + audit_path.write_text(json.dumps(audit, indent=2) + "\n") + + hashes = { + "schema": "dbis-engine-x-canary-proof-hashes/v1", + "generatedAt": generated_at, + "hashAlgorithm": "sha256", + "iso20022DocumentHash": sha256_hex(iso_path), + "pegProofHash": sha256_hex(peg_path), + "auditEnvelopeHash": sha256_hex(audit_path), + "artifacts": {"iso20022": str(iso_path), "pegProof": str(peg_path), "auditEnvelope": str(audit_path)}, + "envExports": { + "DBIS_ENGINE_X_CANARY_ISO20022_HASH": sha256_hex(iso_path), + "DBIS_ENGINE_X_CANARY_AUDIT_HASH": sha256_hex(audit_path), + "DBIS_ENGINE_X_CANARY_PEG_HASH": sha256_hex(peg_path), + }, + } + hashes_path.write_text(json.dumps(hashes, indent=2) + "\n") + return {"iso20022": str(iso_path), "pegProof": str(peg_path), "auditEnvelope": str(audit_path), "proofHashes": str(hashes_path), **hashes["envExports"]} + + +def main() -> int: + args = parse_args() + rpc = os.environ.get("ETHEREUM_MAINNET_RPC") or os.environ.get("MAINNET_RPC_URL") + if not rpc: + raise SystemExit("ETHEREUM_MAINNET_RPC or MAINNET_RPC_URL is required") + deployer = os.environ.get("DEPLOYER_ADDRESS") or DEPLOYER_FALLBACK + private_key_present = bool(os.environ.get("PRIVATE_KEY")) + if private_key_present: + deployer = run(["cast", "wallet", "address", os.environ["PRIVATE_KEY"]]) + + cwusdc = os.environ.get("CWUSDC_MAINNET") or CWUSDC + usdc = os.environ.get("USDC_MAINNET") or USDC + xaut = os.environ.get("XAUT_MAINNET") or XAUT + surplus_receiver = os.environ.get("DBIS_ENGINE_X_SURPLUS_RECEIVER") or deployer + rounding_receiver = os.environ.get("DBIS_ENGINE_X_ROUNDING_RECEIVER") or deployer + + balances = { + "ethWei": first_uint(run(["cast", "balance", deployer, "--rpc-url", rpc], allow_fail=True)) or 0, + "cWUSDCRaw": first_uint(run(["cast", "call", cwusdc, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc], allow_fail=True)) or 0, + "usdCRaw": first_uint(run(["cast", "call", usdc, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc], allow_fail=True)) or 0, + "xautRaw": first_uint(run(["cast", "call", xaut, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc], allow_fail=True)) or 0, + } + gas_price = first_uint(run(["cast", "gas-price", "--rpc-url", rpc], allow_fail=True)) or 0 + + cw_in = get_amount_in(CANARY_DEBT_RAW, CANARY_POOL_RAW, CANARY_POOL_RAW) + cw_reserve_after_in = CANARY_POOL_RAW + cw_in + usdc_reserve_after_out = CANARY_POOL_RAW - CANARY_DEBT_RAW + cw_out = get_amount_out(CANARY_DEBT_RAW, usdc_reserve_after_out, cw_reserve_after_in) + collateral = min_xaut_collateral(CANARY_DEBT_RAW) + proof_id = "0x" + hashlib.sha256(f"dbis-engine-x:canary:{deployer}:{CANARY_DEBT_RAW}".encode()).hexdigest() + + quote_raw = first_uint( + run( + [ + "cast", + "call", + UNISWAP_V3_QUOTER_V2, + "quoteExactInputSingle((address,address,uint256,uint24,uint160))(uint256,uint160,uint32,uint256)", + f"({xaut},{usdc},{XAUT_SWAP_RAW},{XAUT_USDC_FEE},0)", + "--rpc-url", + rpc, + ], + allow_fail=True, + ) + ) or 0 + min_out = quote_raw * 97 // 100 + + deploy_gas = 0 + if not args.skip_deploy_gas_estimate: + project_root = Path(__file__).resolve().parents[2] + smom = project_root / "smom-dbis-138" + run( + ["bash", "scripts/forge/scope.sh", "build", "flash", "--contracts", "contracts/flash/DBISEngineXVirtualBatchVault.sol"], + cwd=str(smom), + allow_fail=False, + ) + artifact = smom / "out/scopes/flash/DBISEngineXVirtualBatchVault.sol/DBISEngineXVirtualBatchVault.json" + bytecode = json.loads(artifact.read_text())["bytecode"]["object"] + deploy_gas = first_uint( + run( + [ + "cast", + "estimate", + "--rpc-url", + rpc, + "--from", + deployer, + "--create", + bytecode, + "constructor(address,address,address,address,address,uint256,uint256,uint256)", + cwusdc, + usdc, + xaut, + deployer, + surplus_receiver, + str(XAUT_USD_PRICE6), + str(LTV_BPS), + str(MAX_ROUND_TRIP_LOSS_BPS), + ], + allow_fail=True, + ) + ) or 0 + + usdc_required = CANARY_POOL_RAW + CANARY_LENDER_RAW + needs_usdc_swap = balances["usdCRaw"] < usdc_required + estimated_post_deploy_gas = 60_000 + 60_000 + 130_000 + 80_000 + 280_000 + estimated_swap_gas = 250_000 if needs_usdc_swap else 0 + gas_units = deploy_gas + estimated_post_deploy_gas + estimated_swap_gas + estimated_cost = gas_units * gas_price + min_eth_reserve = int(Decimal(os.environ.get("DBIS_ENGINE_X_MIN_ETH_RESERVE", "0.002")) * Decimal(10**18)) + + blockers: list[str] = [] + warnings: list[str] = [] + if not private_key_present: + blockers.append("PRIVATE_KEY is not loaded; broadcast is impossible") + if balances["cWUSDCRaw"] < CANARY_POOL_RAW + cw_in: + blockers.append("deployer cWUSDC is below canary seed plus canary input") + if balances["xautRaw"] < collateral + (XAUT_SWAP_RAW if needs_usdc_swap else 0): + blockers.append("deployer XAUt is below canary collateral plus proposed XAUt->USDC swap") + if needs_usdc_swap and quote_raw < usdc_required: + blockers.append("quoted XAUt->USDC output is below canary USDC seed requirement") + if balances["ethWei"] < estimated_cost + min_eth_reserve: + blockers.append("deployer ETH is below estimated canary path cost plus reserve") + if needs_usdc_swap: + warnings.append("wallet USDC is zero/insufficient; canary requires a small XAUt->USDC swap before seed/fund") + if not os.environ.get("ETHERSCAN_API_KEY"): + warnings.append("ETHERSCAN_API_KEY is missing; source verification will need a manual follow-up") + + payload = { + "schema": "dbis-engine-x-virtual-batch-canary-preflight/v1", + "generatedAt": datetime.now(timezone.utc).replace(microsecond=0).isoformat(), + "classification": "read_only_no_broadcast", + "deployer": deployer, + "tokens": {"cWUSDC": cwusdc, "USDC": usdc, "XAUt": xaut}, + "constructor": { + "owner": deployer, + "surplusReceiver": surplus_receiver, + "xautUsdPrice6": str(XAUT_USD_PRICE6), + "ltvBps": str(LTV_BPS), + "maxRoundTripLossBps": str(MAX_ROUND_TRIP_LOSS_BPS), + }, + "receivers": {"surplusReceiver": surplus_receiver, "roundingReceiver": rounding_receiver}, + "balances": { + **{k: str(v) for k, v in balances.items()}, + "eth": eth(balances["ethWei"]), + "cWUSDC": human(balances["cWUSDCRaw"]), + "USDC": human(balances["usdCRaw"]), + "XAUt": human(balances["xautRaw"]), + "gasPriceWei": str(gas_price), + }, + "canary": { + "poolSeedRaw": str(CANARY_POOL_RAW), + "poolSeed": human(CANARY_POOL_RAW), + "lenderSeedRaw": str(CANARY_LENDER_RAW), + "lenderSeed": human(CANARY_LENDER_RAW), + "debtRaw": str(CANARY_DEBT_RAW), + "debt": human(CANARY_DEBT_RAW), + "cwusdcInRaw": str(cw_in), + "cwusdcIn": human(cw_in), + "cwusdcOutRaw": str(cw_out), + "cwusdcOut": human(cw_out), + "exactOutputRaw": str(cw_out), + "exactOutput": human(cw_out), + "collateralXautRaw": str(collateral), + "collateralXaut": human(collateral), + "proofId": proof_id, + }, + "xautToUsdcPrep": { + "needed": needs_usdc_swap, + "router": UNISWAP_SWAP_ROUTER_02, + "quoter": UNISWAP_V3_QUOTER_V2, + "fee": XAUT_USDC_FEE, + "xautInRaw": str(XAUT_SWAP_RAW), + "xautIn": human(XAUT_SWAP_RAW), + "quotedUsdcOutRaw": str(quote_raw), + "quotedUsdcOut": human(quote_raw), + "minUsdcOutRaw": str(min_out), + "minUsdcOut": human(min_out), + }, + "gas": { + "deployGasEstimate": str(deploy_gas), + "estimatedPostDeployGas": str(estimated_post_deploy_gas), + "estimatedSwapGas": str(estimated_swap_gas), + "estimatedTotalGasUnits": str(gas_units), + "estimatedCostWei": str(estimated_cost), + "estimatedCostEth": eth(estimated_cost), + "minimumEthReserveWei": str(min_eth_reserve), + "minimumEthReserve": eth(min_eth_reserve), + }, + "blockers": blockers, + "warnings": warnings, + } + payload["proofArtifacts"] = write_canary_artifacts(Path(args.artifact_prefix), payload) + payload["operatorCommands"] = { + "note": "Review-only. These commands intentionally omit --broadcast orchestration.", + "deploy": ( + "forge create --broadcast --verify --rpc-url \"$ETHEREUM_MAINNET_RPC\" --private-key \"$PRIVATE_KEY\" " + "contracts/flash/DBISEngineXVirtualBatchVault.sol:DBISEngineXVirtualBatchVault " + f"--constructor-args {cwusdc} {usdc} {xaut} {deployer} {surplus_receiver} " + f"{XAUT_USD_PRICE6} {LTV_BPS} {MAX_ROUND_TRIP_LOSS_BPS}" + ), + "xautApproveForSwap": f'cast send {xaut} "approve(address,uint256)" {UNISWAP_SWAP_ROUTER_02} {XAUT_SWAP_RAW} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + "xautSwapForUsdc": ( + f'cast send {UNISWAP_SWAP_ROUTER_02} ' + '"exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))(uint256)" ' + f'"({xaut},{usdc},{XAUT_USDC_FEE},{deployer},$(($(date +%s)+600)),{XAUT_SWAP_RAW},{min_out},0)" ' + '--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"' + ), + "approveSeedTokens": [ + f'cast send {cwusdc} "approve(address,uint256)" "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" {CANARY_POOL_RAW + cw_in} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + f'cast send {usdc} "approve(address,uint256)" "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" {usdc_required} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + f'cast send {xaut} "approve(address,uint256)" "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" {collateral} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + ], + "seedAndFund": [ + f'cast send "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" "seedPool(uint256,uint256)" {CANARY_POOL_RAW} {CANARY_POOL_RAW} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + f'cast send "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" "fundLender(uint256)" {CANARY_LENDER_RAW} --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"', + ], + "runExactOutputCanary": ( + 'cast send "$DBIS_ENGINE_X_VIRTUAL_BATCH_VAULT" ' + '"runVirtualProofExactOutTo(bytes32,uint256,uint256,address,uint256,address,bytes32,bytes32,bytes32)" ' + f'{proof_id} {CANARY_DEBT_RAW} 1 {deployer} {cw_out} {rounding_receiver} ' + '"$DBIS_ENGINE_X_CANARY_ISO20022_HASH" "$DBIS_ENGINE_X_CANARY_AUDIT_HASH" "$DBIS_ENGINE_X_CANARY_PEG_HASH" ' + '--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"' + ), + } + + json_path = Path(args.json_out) + md_path = Path(args.md_out) + json_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, "warnings": warnings}, indent=2)) + return 0 + + +def render_markdown(payload: dict) -> str: + lines = [ + "# DBIS Engine X Virtual Batch Canary Preflight", + "", + f"Generated: `{payload['generatedAt']}`", + "", + "Classification: read-only preflight. No transaction was broadcast.", + "", + "## Summary", + "", + f"- Deployer: `{payload['deployer']}`", + f"- ETH: `{payload['balances']['eth']}`", + f"- cWUSDC: `{payload['balances']['cWUSDC']}`", + f"- USDC: `{payload['balances']['USDC']}`", + f"- XAUt: `{payload['balances']['XAUt']}`", + f"- Estimated full canary path cost: `{payload['gas']['estimatedCostEth']} ETH`", + f"- Minimum ETH reserve: `{payload['gas']['minimumEthReserve']} ETH`", + "", + "## Canary", + "", + f"- Seed: `{payload['canary']['poolSeed']} cWUSDC / {payload['canary']['poolSeed']} USDC`", + f"- Lender: `{payload['canary']['lenderSeed']} USDC`", + f"- Debt: `{payload['canary']['debt']} USDC`", + f"- cWUSDC in/out: `{payload['canary']['cwusdcIn']} / {payload['canary']['cwusdcOut']}`", + f"- XAUt collateral: `{payload['canary']['collateralXaut']} XAUt`", + f"- Proof ID: `{payload['canary']['proofId']}`", + "", + "## Canary Proof Hashes", + "", + f"- ISO 20022-style XML: `{payload['proofArtifacts']['DBIS_ENGINE_X_CANARY_ISO20022_HASH']}`", + f"- Audit envelope: `{payload['proofArtifacts']['DBIS_ENGINE_X_CANARY_AUDIT_HASH']}`", + f"- Peg proof: `{payload['proofArtifacts']['DBIS_ENGINE_X_CANARY_PEG_HASH']}`", + "", + "## Blockers", + "", + ] + if payload["blockers"]: + lines.extend([f"- {item}" for item in payload["blockers"]]) + else: + lines.append("- No read-only preflight blockers found.") + lines.extend(["", "## Warnings", ""]) + if payload["warnings"]: + lines.extend([f"- {item}" for item in payload["warnings"]]) + else: + lines.append("- None.") + lines.extend( + [ + "", + "## Notes", + "", + "- Wallet USDC must be present before seed/fund, or the tiny quoted XAUt->USDC prep swap must be broadcast first.", + "- The canary proves the new virtual-batch exact-output and hash-anchor path, not public DEX peg repair.", + "- Keep the 5B proof hashes separate from these canary hashes.", + ] + ) + return "\n".join(lines) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.sh b/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.sh new file mode 100755 index 00000000..11690048 --- /dev/null +++ b/scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +if [[ -f "$PROJECT_ROOT/scripts/lib/load-project-env.sh" ]]; then + # shellcheck disable=SC1090 + PROJECT_ROOT="$PROJECT_ROOT" source "$PROJECT_ROOT/scripts/lib/load-project-env.sh" +fi + +cd "$PROJECT_ROOT" +python3 scripts/verify/preflight-dbis-engine-x-virtual-batch-canary.py "$@" diff --git a/smom-dbis-138 b/smom-dbis-138 index bb648368..27f8e3a5 160000 --- a/smom-dbis-138 +++ b/smom-dbis-138 @@ -1 +1 @@ -Subproject commit bb64836886efb48b72596ef9c306c306aee5440d +Subproject commit 27f8e3a500d4ee49274d5598ac704669bf8cf2fb