Skip to content

feat: ERC6492 for Permit2#1488

Merged
grasphoper merged 2 commits into
feat/erc6492-signature-handlingfrom
feat/erc6492-signature-handling-permit2
Jul 6, 2026
Merged

feat: ERC6492 for Permit2#1488
grasphoper merged 2 commits into
feat/erc6492-signature-handlingfrom
feat/erc6492-signature-handling-permit2

Conversation

@grasphoper

Copy link
Copy Markdown
Collaborator

No description provided.

Signed-off-by: Ihor Farion <ihor@umaproject.org>
@grasphoper grasphoper merged commit 5d578e0 into feat/erc6492-signature-handling Jul 6, 2026
9 checks passed
@grasphoper grasphoper deleted the feat/erc6492-signature-handling-permit2 branch July 6, 2026 02:38
grasphoper added a commit that referenced this pull request Jul 6, 2026
…llet signers (#1467)

* feat(SpokePoolPeriphery): support ERC-6492 counterfactual signers

The bytes-signature ERC-3009 entry points (depositWithAuthorizationBytes,
swapAndBridgeWithAuthorizationBytes) delegate signature verification to the
token (e.g. USDC v2.2), which supports EIP-1271 contract wallets but has no
concept of ERC-6492. A *counterfactual* (not-yet-deployed) contract wallet
therefore cannot authorize a transfer, since there is no code at the signer's
address to run isValidSignature on.

We cannot change the token's verification, so we replicate only the deploy half
of the ERC-6492 flow: a new ERC6492SignatureHandler base contract detects the
ERC-6492 magic suffix and, if present, runs the wrapped factory call to
materialize the wallet before handing the unwrapped inner signature to the
token. The token's own EIP-1271 check then succeeds against the deployed signer.

The factory target/calldata are attacker-controlled, so the prepare call is
routed through the canonical Multicall3 singleton (supplied as an immutable
constructor arg) — this contract is never the msg.sender of that call, so it
cannot be tricked into abusing its own allowances. The call uses
requireSuccess=false so an already-deployed wallet is tolerated; the token
remains the source of truth on validity. Mirrors Coinbase's
ERC6492SignatureHandler (base/commerce-payments).

- New IMulticall3 interface and ERC6492SignatureHandler base contract.
- SpokePoolPeriphery inherits it; constructor now takes the Multicall3 address.
- Deploy script + Constants.getMulticall3() pass the canonical 0xcA11...CA11.
- Non-ERC-6492 signatures pass through unchanged (existing bytes/EIP-1271/EOA
  tests continue to exercise the passthrough path).

Test plan:
- yarn build-evm-foundry
- yarn test-evm-foundry -- --match-contract "SpokePoolPeripheryTest|TransferProxy"
  53 passed (49 existing + 4 new)
- New tests: counterfactual-wallet deposit & swap-and-bridge, already-deployed
  wallet with wrapped sig (idempotent prepare), and failing-prepare tolerance.
- yarn lint-fix

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(tron): forward multicall3 arg to SpokePoolPeriphery deploy

The new SpokePoolPeriphery constructor requires a Multicall3 address; the
Tron deployment script was still encoding only `<permit2>`, so the
documented `yarn tron-deploy-spoke-pool-periphery` flow would have
reverted in the constructor's zero-address check. Take a second Tron
Base58Check address, validate it, and ABI-encode it as the second arg.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* perf(ERC6492SignatureHandler): decode wrapped signature from calldata

Take the signature as calldata and decode the (factory, factoryCalldata,
innerSignature) tuple directly from a calldata slice. Drops the entry
calldata-to-memory copy and the byte-by-byte loop into a memory scratch
buffer that used to precede abi.decode.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(ERC6492SignatureHandler): use magic-value length over literal 32

Replace the hard-coded 32 magic-suffix length with _ERC6492_MAGIC_VALUE.length
(a compile-time constant for the bytes32) so the length check and the calldata
slices are self-documenting and stay in sync with the constant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* move isContract check && add Permit2 handling of erc6492 (#1488)

Signed-off-by: Ihor Farion <ihor@umaproject.org>

* named fn arguments

Signed-off-by: Ihor Farion <ihor@umaproject.org>

---------

Signed-off-by: Ihor Farion <ihor@umaproject.org>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: droplet-rl <284132418+droplet-rl@users.noreply.github.com>
Co-authored-by: Ihor Farion <ihor@umaproject.org>
Co-authored-by: grasphoper <65650773+grasphoper@users.noreply.github.com>
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