Skip to content

fix: gate Money Account payment override prepend to same-chain flows#9449

Open
OGPoyraz wants to merge 4 commits into
mainfrom
ogp/fix-money-account-cross-chain-invalid-eoa-signature
Open

fix: gate Money Account payment override prepend to same-chain flows#9449
OGPoyraz wants to merge 4 commits into
mainfrom
ogp/fix-money-account-cross-chain-invalid-eoa-signature

Conversation

@OGPoyraz

@OGPoyraz OGPoyraz commented Jul 9, 2026

Copy link
Copy Markdown
Member

Explanation

Cross-chain Money Account deposits — e.g. a Predict (Polymarket) withdrawal on Polygon that deposits into a Money Account on Monad — failed on the Relay /execute step with the custom error InvalidEOASignature() (selector 0x3db6791c).

Current state: submitTransactions unconditionally prepends the Money Account payment override onto the source-chain execute batch whenever quote.request.paymentOverride is set. For a cross-chain deposit, the payment override is a Money Account deposit delegation that belongs on the destination chain — it is already carried in the Relay quote's destination txs[], and its delegation is EIP-712 signed for the destination chainId. Prepending it onto the source-chain batch caused that destination-signed delegation to be redeemed on the source chain, so redeemDelegationsexecuteFromExecutor validated the signature with the source chain's domain, recovered a different signer, and the EIP7702StatelessDeleGator reverted with InvalidEOASignature().

Solution: Only prepend the payment override onto the source execute batch for same-chain flows (currencyIn.chainId === currencyOut.chainId). For cross-chain flows we fall through to the existing post-quote path, which prepends the original transaction (e.g. the Predict withdrawal); the Money Account deposit continues to run on the destination side via the quote's txs[].

The change is a one-line guard (&& isSameChainOverride) plus a comment explaining the invariant.

Proof

Before the fix, the Relay /execute simulation returned (decoded revert trace):

Multicall3.aggregate3Value
└─ redeemDelegations                @ 0xdb9b1e94… (DelegationManager, source chain 137)
   └─ executeFromExecutor           @ 0x6d404afe… (7702 account)
      └─ redeemDelegations          @ 0xdb9b1e94…
         └─ revert 0x3db6791c = InvalidEOASignature()

The delegation being redeemed was signed for the destination chain (Monad, chainId 143) but executed on the source chain (Polygon, chainId 137) — confirmed via signDelegation logs showing domain.chainId: 143 for the Money Account delegation while the execute body used data.chainId: 137.

After the fix, the cross-chain source batch no longer contains the destination-signed override, so the InvalidEOASignature() revert no longer occurs.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Touches Relay submit batch composition for paymentOverride flows; wrong gating could break same-chain Money Account deposits or leave cross-chain paths unchanged.

Overview
Fixes cross-chain Money Account deposits (e.g. Predict withdraw on Polygon → Money Account on another chain) failing Relay /execute with InvalidEOASignature() by changing when the Money Account payment override is injected into the source-chain batch.

submitTransactions in relay-submit.ts now prepends override calls from getPaymentOverrideData only when paymentOverride is set and currencyIn.chainId === currencyOut.chainId. For cross-chain quotes, the override delegation is already on the destination txs[] and is EIP-712 signed for the destination chain; putting it on the source batch caused wrong-domain signature recovery. Cross-chain flows skip the override prepend (and getPaymentOverrideData) and use the existing post-quote behavior (e.g. prepend the original withdraw tx).

Tests align same-chain override cases and add coverage that cross-chain flows do not call getPaymentOverrideData. Changelog updated under Fixed.

Reviewed by Cursor Bugbot for commit cc17bcb. Bugbot is set up for automated code reviews on this repo. Configure here.

Cross-chain flows (e.g. Predict withdraw on Polygon depositing to a Money
Account on Monad) carry the deposit in the Relay quote's destination txs[]
with a delegation signed for the destination chain. Prepending it onto the
source-chain execute batch made that delegation get redeemed on the source
chain, so the on-chain signature check recovered a wrong signer and reverted
with InvalidEOASignature() (0x3db6791c). Only prepend the override for
same-chain flows; cross-chain flows fall through to prepend the original tx.
@OGPoyraz OGPoyraz requested review from a team as code owners July 9, 2026 13:53
@OGPoyraz OGPoyraz temporarily deployed to default-branch July 9, 2026 13:53 — with GitHub Actions Inactive
@matthewwalsh0 matthewwalsh0 requested a review from jpuri July 9, 2026 14:08
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