Skip to content

feat(swap): support EIP-7702 wrapping delegates (ERC-7739 / MA v2) for CoW orders#2984

Closed
mgrabina wants to merge 1 commit into
mainfrom
martin/sdk-823-wrapping-delegate-support
Closed

feat(swap): support EIP-7702 wrapping delegates (ERC-7739 / MA v2) for CoW orders#2984
mgrabina wants to merge 1 commit into
mainfrom
martin/sdk-823-wrapping-delegate-support

Conversation

@mgrabina
Copy link
Copy Markdown
Contributor

Summary

  • Adds a third wallet branch in the CoW swap flow for EIP-7702 delegated EOAs whose delegate wraps signatures at sign time (ERC-7739 nested typed data, ERC-7579 / Modular Account v2 validator prefix, or both).
  • Branching today:
    • contract -> setPreSignature on-chain (unchanged)
    • delegated-eoa-wrapping -> EIP-1271 off-chain via customEIP1271Signature (new)
    • eoa / delegated-eoa-plain -> EIP-712 off-chain (unchanged)
  • Allowlist of wrapping delegates is empty today, so the new branch is unreachable. Production behavior unchanged at merge.

Why now

Production EOAs are increasingly running 7702 delegates. The dominant delegate today (Metamask Smart Account) returns raw ECDSA from signTypedData_v4 and works via the existing EIP-712 path. Delegates that force ERC-7739 / ERC-7579 wrapping return non-65-byte bytes that don't ecrecover to the owner — CoW's EIP-712 path rejects them. This PR routes those orders through EIP-1271 instead, with the bytes forwarded verbatim to CoW's isValidSignature check on the EOA address (which EIP-7702 dispatches to the delegate).

Cross-repo coordination

  • cow-sdk: cowprotocol/cow-sdk#878 adds the canonical classifyAccount + signOrderForWrappingDelegate helpers. This PR vendors them in src/helpers/eip7702.ts; swap to the upstream import once the cow-sdk PR merges and ships in a release.
  • aave-backend: aave/aave-backend-monorepo#614 adds the equivalent backend classification + routing for the v4 API path.

What changed

  • src/helpers/eip7702.ts (new) — classifyAccount(user, provider) returns 'eoa' | 'delegated-eoa-plain' | 'delegated-eoa-wrapping' | 'contract' based on eth_getCode and a WRAPPING_DELEGATES allowlist (empty today). Vendored from cow-sdk PR until upstream releases.
  • src/components/transactions/Swap/helpers/cow/orders.helpers.ts — adds sendOrderForWrappingDelegate that calls tradingSdk.postLimitOrder with additionalParams.signingScheme: SigningScheme.EIP1271 and a customEIP1271Signature callback. The callback uses OrderSigningUtils.signOrder to do typed-data signing; the wallet wraps internally per its delegate's spec, and the resulting bytes are forwarded verbatim (no (order, sig) ABI tuple wrap, unlike the SDK's default EIP-1271 path).
  • src/components/transactions/Swap/actions/SwapActions/SwapActionsViaCoW.tsx — replaces the existing isSmartContractWallet ? presign : sendOrder binary with the three-way classifyAccount branch.

Backwards compatibility

  • Legacy isSmartContractWallet helper at src/helpers/provider.ts is untouched and still consumed by useUserContext, useGetConnectedWalletType, useSwapTokenApproval, and orders.helpers.ts (for the EOA-only sendOrder guard).
  • The contract / eoa / delegated-eoa-plain branches all execute the same code paths as before this PR. Only delegated-eoa-wrapping triggers new code, and that branch is gated on the empty allowlist.
  • Allowlist additions are local code changes; no schema migration, no SDK API change required.

Codex backwards-compat review

Ran codex exec against the diff. Findings:

  • Medium (resolved): src/helpers/eip7702.ts was untracked at audit time; now committed in this push.
  • Low: classifyAccount is stricter than the legacy isEip7702EOA (drops the code === account fallback the legacy helper had). Standard EIP-7702 delegation behavior is preserved per the spec.
  • Low: OrderSigningUtils.signOrder has v3/eth_sign fallbacks on RPC errors; once wrapping delegates are populated, this path depends on those delegates supporting the typed-data flow (expected).
  • Verified: SDK-trading's customEIP1271Signature type matches our callback signature; default (order, sig) ABI wrap is correctly bypassed when the callback is provided.

Verification

  • ./node_modules/.bin/tsc --noEmit -p tsconfig.json: clean
  • ./node_modules/.bin/prettier ... --check: clean

Related Linear: SDK-823.

…r CoW orders

Three-way wallet branching in the CoW swap flow:

- contract                  -> setPreSignature on-chain (unchanged)
- delegated-eoa-wrapping    -> EIP-1271 off-chain via customEIP1271Signature
- eoa / delegated-eoa-plain -> EIP-712 off-chain (unchanged)

New `classifyAccount` helper (src/helpers/eip7702.ts) vendored from the
cow-sdk proposal in cowprotocol/cow-sdk#878; drop when upstream merges.
Inspects on-chain code for the canonical 23-byte 0xef0100 marker and
looks the delegate up in a `WRAPPING_DELEGATES` allowlist. The allowlist
is empty today, so the new wrapping branch is unreachable until populated.

New `sendOrderForWrappingDelegate` in cow/orders.helpers.ts uses
`tradingSdk.postLimitOrder` with `additionalParams.signingScheme:
SigningScheme.EIP1271` and a `customEIP1271Signature` callback that
forwards the wallet's raw signTypedData bytes verbatim — no `(order, sig)`
ABI tuple wrap. CoW resolves verification via `isValidSignature` on the
EOA, which EIP-7702 dispatches to the delegate.

Production behavior is unchanged the day this lands. The new path
activates only once known wrapping delegates are added to the allowlist
(Alchemy MA v2, ZeroDev Kernel v3, Biconomy Nexus, etc.).

Reviewed with codex; no blocking compatibility issues.
@linear
Copy link
Copy Markdown

linear Bot commented May 15, 2026

SDK-823

@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
interface Ready Ready Preview, Comment May 15, 2026 2:25pm

Request Review

@github-actions
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

📦 Next.js Bundle Analysis for aave-ui

This analysis was generated by the Next.js Bundle Analysis action. 🤖

This PR introduced no changes to the JavaScript bundle! 🙌

@mgrabina
Copy link
Copy Markdown
Contributor Author

Superseded by cow-sdk-side auto-routing (no interface-v3 changes needed). New cow-sdk PR will detect wrapped sigs by byte length in postCoWProtocolTrade default path and auto-route to EIP1271. Linear: SDK-823.

@mgrabina mgrabina closed this May 15, 2026
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.

1 participant