Skip to content

feat(auth): support ERC-6492 signatures for predeployed smart accounts#3683

Draft
joshuakrueger-dfx wants to merge 1 commit intoDFXswiss:developfrom
joshuakrueger-dfx:feature/wdk-erc6492-auth
Draft

feat(auth): support ERC-6492 signatures for predeployed smart accounts#3683
joshuakrueger-dfx wants to merge 1 commit intoDFXswiss:developfrom
joshuakrueger-dfx:feature/wdk-erc6492-auth

Conversation

@joshuakrueger-dfx
Copy link
Copy Markdown
Contributor

Summary

Enables wallets such as Tether's WDK (@tetherto/wdk-wallet-evm-erc-4337) to sign in to DFX before their Safe-style smart account has been deployed on-chain. Currently the EVM auth path verifies ECDSA EOA sigs (fast) and ERC-1271 sigs from already-deployed contracts; counterfactual smart accounts fail. This PR adds ERC-6492 universal verification.

What changed

  • NEW erc6492-validator.const.ts — audited Ambire deployless UniversalSigValidator bytecode + ERC-6492 magic suffix
  • NEW EvmClient.verifyErc6492Signature() — single eth_call covers ERC-6492 (counterfactual) + ERC-1271 (deployed) + ecrecover; returns false on any error, never throws
  • NEW EvmUtil.hasErc6492MagicSuffix() — cheap detector to gate the smart-account path
  • MOD CryptoService.verifyEthereumBased() — flow becomes:
    1. ECDSA local verify (fast path, EOAs)
    2. On miss, if 6492 magic suffix detected OR address is a deployed contract → universal validator
    3. Else false (no extra RPC for plain garbage sigs)

The same cryptoService.verifySignature is the only sig-check used by authService.signIn / signUp / challenge, so all wallet-registration paths are covered without touching auth.service or the user/wallet domain.

Behaviour matrix

Sign-in case Path RPC?
Valid EOA sig ECDSA local no
Deployed smart wallet (1271) universal validator 1 call
Counterfactual WDK Safe (6492) universal validator 1 call
Garbage sig on EOA address ECDSA fail → no further checks no
Garbage sig on contract address ECDSA fail → universal validator returns 0x00 1 call

Test plan

  • tsc --noEmit -p tsconfig.json clean
  • eslint clean across all touched files
  • 55/55 tests pass across 5 spec files:
    • erc6492-validator.const.spec.ts (9) — bytecode/suffix integrity
    • evm-client-erc6492.spec.ts (5) — calldata encoding, return handling, RPC error handling (mocked provider)
    • evm.util.spec.ts (15, +6 new) — magic suffix detector edge cases
    • crypto.service.spec.ts (19) — existing routing tests stay green
    • crypto.service.evm.spec.ts (7) — full verifyEthereumBased flow with mocked registry/EvmClient
  • Live integration test against Citrea testnet with a real WDK fixture — follow-up, mirrors the describeIfApiKey pattern from paymaster/__tests__/pimlico-bundler.integration.spec.ts

Out of scope (verified, not needed for this PR)

  • Receive-address registration — uses the same cryptoService.verifySignature, automatically covered
  • DFX-side gasless ops — separate strand; EIP-7702 already in production via swap.service.ts / sell.service.ts / realunit.service.ts. WDK is self-custodial: user signs their own UserOps, DFX only validates sign-in + receive address (both covered here)

References

Enables wallets such as Tether's WDK (@tetherto/wdk-wallet-evm-erc-4337) to
sign in to DFX before their Safe-style smart account has been deployed
on-chain. The existing EVM auth path verifies ECDSA EOA sigs (fast) and
ERC-1271 sigs from already-deployed contracts; counterfactual smart accounts
fail.

- EvmClient.verifyErc6492Signature: delegates to viem's PublicClient.verifyMessage,
  which transparently dispatches to ERC-6492 (counterfactual) / ERC-1271
  (deployed) / ecrecover. Same viem + getEvmChainConfig setup the existing
  Pimlico services already use for AA concerns.
- EvmUtil.hasErc6492MagicSuffix: cheap detector to gate the smart-account path
  and avoid an unnecessary RPC roundtrip on plain EOA sigs.
- CryptoService.verifyEthereumBased: ECDSA local fast-path → on miss, if 6492
  magic suffix detected OR address is a deployed contract → universal
  validator → else false.

The same cryptoService.verifySignature is the only sig-check used by
authService.signIn / signUp / challenge, so all wallet-registration paths are
covered without touching auth.service or the user/wallet domain.

Tests:
- evm.util.spec.ts: 6 new cases for hasErc6492MagicSuffix
- crypto.service.evm.spec.ts: 7 cases covering the full verifyEthereumBased
  flow with Test.createTestingModule + createMock<T> from @golevelup/ts-jest
@joshuakrueger-dfx joshuakrueger-dfx force-pushed the feature/wdk-erc6492-auth branch from 5b8e84f to 00e9b8b Compare May 8, 2026 13:45
@joshuakrueger-dfx joshuakrueger-dfx marked this pull request as draft May 8, 2026 19:34
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