Skip to content

managed-oracle: add one-signature partial-success proposal batches - #79

Merged
chrismaree merged 9 commits into
masterfrom
chrismaree/signed-proposer-batch
Oct 5, 2026
Merged

chrismaree merged 9 commits into
masterfrom
chrismaree/signed-proposer-batch

Conversation

@chrismaree

@chrismaree chrismaree commented Sep 8, 2026 •

Copy link
Copy Markdown
Member

What Changed

  • Adds proposeBatch: one signer, one collateral token, one Permit2 witness signature and nonce for an ordered batch of proposals.
  • Signs each proposal's bond-plus-payment budget, funds the total once, executes items independently, and refunds unused funds at the end. Successful items persist when another item fails.
  • Adds authorization, accounting, replay, tampering, reentrancy, refund rollback, and Polygon capacity coverage, plus a Permit2 SDK/ethers signing example.
  • Integrates current master (886c23b) and targets master directly. Preserves master's ERC-7201 TryMulticall lock, 256-byte revert-data cap, reporter consolidation, and existing regression coverage.

Why

  • Users proposing on several markets can authorize the batch with one typed-data signature.
  • Signed per-item budgets preserve spending isolation; retries require a fresh signature and unused nonce.
  • The earlier UUPS/tryMulticall work is already integrated into master and is not additional feature scope in this diff.

Impact

  • Existing propose, atomic multicall, and tryMulticall remain available; tryMulticall still accepts only propose calls.
  • Adds no persistent storage or initializer changes relative to master. The funded helper is self-call-only and the outer batch holds the reentrancy guard.
  • A completed batch consumes its nonce even if every item fails. Invalid funding/signatures, final refund failure, or an outer revert undo the entire transaction.
  • Scope is four files covering the contract, regression tests, and signing/integration documentation.

High risk Sections to review with detail

  • Authorization and accounting: nested EIP-712 type ordering and array hashing; individual budgets; exact token receipt; bounded oracle allowances; actual bond balance deltas; refunds excluding pre-existing balances.
  • Failure isolation: failed child token movements, approvals, and whitelist changes roll back. Final refund failure rolls back successful siblings too.
  • Gas and revert data: proposeBatch copies and hashes at most the first 256 bytes of child revert data, matching tryMulticall. Success reads exactly one 32-byte spend value. There is still no child gas cap: the trusted delegated relayer controls batch construction and transaction gas, and requester callbacks can still starve later work or cause an outer revert. This gas-allocation tradeoff is intentionally retained.
  • Polygon capacity: 15 proposals with 8,139-byte ancillary data and a 65-byte signature encode to 128,612 calldata bytes; 16 encode to 137,156 and exceed Bor's 128 KiB transaction limit. Contract-wallet signatures and access lists need separate sizing.

Validation

  • Bounded-revert-data follow-up (621b4d3): added regression cases for 0, 3, 4, 256, 257, and 524,288-byte errors, checking prefix hashes/selectors, successful siblings, refunds, retained balances, and revoked allowances. These new tests were not run, per repository instructions. Static diff review and git diff --check passed; no builds/tests were executed and CI is not awaited.

  • Investigated failed CI run 34257141893. The Foundry project, reporter package, and production-upgrade fork jobs passed. The Polygon fork job failed seven checks with RPC -32000: metadata is not found, 72928559 while loading account/storage state, including Permit2 and USDC.e. The apparent expectRevert failure also follows an RPC failure in vm.prank.

  • No contract assertion fix or weakened fork coverage is justified by those logs. If the failure recurs, the configured Polygon RPC needs investigation for historical-state availability.

  • After master integration: Foundry 1.3.6 formatting checks and git diff --check passed. Verified the batching test patch matches the original PR exactly and master-only hardening is retained.

  • No builds or tests were run locally during this update, per repository instructions. Earlier branch validation recorded 81 passing targeted tests plus isolated capacity coverage; those results predate the master integration.

  • Fresh CI is triggered by the push and has not been awaited. The SDK signing example has not been runtime-tested.

TL;DR: One signature funds an ordered same-token batch. This four-file PR now targets current master; most additions are tests. The observed CI failure is missing Polygon RPC state, and fresh CI must confirm whether the endpoint has recovered.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-08T17:22:19.313869Z 3332f8a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@md0x md0x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the batching design, EIP-712 witness encoding, budget/refund accounting, reentrancy surface, and test coverage at a4003bc. The witness type strings compose correctly with Permit2, per-item budgets are enforced via scoped allowances with balance-diff accounting, and the only-self execution boundary plus the shared reentrancy guard hold across the paths I could construct. Tests are thorough, including real-Permit2 signature verification, tamper fuzzing, refund-failure atomicity, gas exhaustion, and Polygon capacity bounds. No blockers found.

@chrismaree
chrismaree changed the base branch from chrismaree/signed-proposer-uups to master September 28, 2026 13:27
* @param payments Actual per-item payments, bounded by each signed proposal.maxPayment.
* @return successes Per-item execution results. Failed items require a fresh signed batch to retry.
*/
function proposeBatch(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the unbounded revert-data handling in commit 621b4d3.

  • Replaced the high-level catch with a self-call that does not automatically allocate all return data. Failed items copy/hash at most the first 256 bytes, matching tryMulticall; errors shorter than four bytes retain a zero selector. Successful calls read exactly one 32-byte spent value.
  • Preserved per-item rollback, budget/refund accounting, role checks, and the outer reentrancy guard. Updated the event documentation and README to specify the truncated-prefix hash.
  • Added regression coverage for 0, 3, 4, 256, 257, and 524,288-byte errors, including successful siblings, refunds, retained balances, and allowance cleanup.

As discussed with Chris, no per-child gas cap is added: the delegated caller is trusted to construct the batch and choose transaction gas. Requester callbacks can still consume gas unexpectedly, so this remains an explicit execution limitation rather than a guarantee of sibling gas isolation.

Validation: static diff review and git diff --check passed. Builds/tests were not run under the repository instruction; the new regression cases remain unexecuted locally. Pushed to this PR without waiting for CI.

Chris's Codex agent · human-approved

@chrismaree
chrismaree merged commit 24a5930 into master Oct 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants