Skip to content

Add universal signature verification (ERC-1271 + ERC-6492)#266

Merged
alisinabh merged 4 commits into
mainfrom
feat/universal-sig-verification
Jul 19, 2026
Merged

Add universal signature verification (ERC-1271 + ERC-6492)#266
alisinabh merged 4 commits into
mainfrom
feat/universal-sig-verification

Conversation

@alisinabh

Copy link
Copy Markdown
Member

Second PR of the v0.7 "Auth" tier. Stacked on #265 (base is feat/eip-191-personal-message; retarget to main after #265 merges).

What

  • New Ethers.Signature module: verify_hash/4, verify_message/4 (EIP-191), verify_typed_data/4 (EIP-712) — verifies any signature: EOA ecrecover, ERC-1271 smart-contract wallets, and ERC-6492-wrapped signatures from counterfactual (not-yet-deployed) wallets.
  • Fast path: plain 65-byte ECDSA signatures that ecrecover to the expected address return {:ok, true} with zero RPC calls. Everything else goes through one deployless eth_call of the ERC-6492 UniversalSigValidator (creation code as call data, no to).
  • lib/ethers/contracts/universal_sig_validator.ex holds the validator creation bytecode (sourced from viem's erc6492SignatureValidatorByteCode, i.e. Ambire's ERC-6492 reference ValidateSigOffchain; provenance documented).
  • Semantics: {:ok, false} for invalid signatures (incl. validator reverts on malformed input); {:error, reason} only for transport failures. No bang variants — they would conflate false with errors.

Testing

  • TDD; 100% coverage on Ethers.Signature incl. all branches.
  • Real end-to-end tests on anvil: deployed ERC-1271 wallet fixture (accept/reject), and a CREATE2-counterfactual wallet verified via a hand-built 6492 wrapper without ever deploying it (asserted undeployed before and after).
  • No-RPC fast path proven with a raising RPC stub; deployless call shape asserted via an echoing RPC stub.
  • Full suite green; mix format, mix credo --strict, mix dialyzer clean.

🤖 Generated with Claude Code

@alisinabh
alisinabh force-pushed the feat/eip-191-personal-message branch from adbc89c to 4ed65a5 Compare July 19, 2026 04:29
@alisinabh
alisinabh force-pushed the feat/universal-sig-verification branch from ebe1cac to 6997141 Compare July 19, 2026 04:29
Base automatically changed from feat/eip-191-personal-message to main July 19, 2026 04:35
alisinabh and others added 2 commits July 19, 2026 00:36
Add Ethers.Signature with verify_hash/4, verify_message/4 and
verify_typed_data/4, verifying any signature kind against an address:

- Plain EOA ECDSA signatures verify locally via ecrecover with no RPC
  round-trip (fast path).
- ERC-1271 smart-contract wallet signatures and ERC-6492-wrapped
  signatures from counterfactual (not-yet-deployed) wallets verify with
  a single deployless eth_call executing the ERC-6492
  UniversalSigValidator reference contract (bytecode vendored from
  viem / Ambire signature-validator, shipped as a constant in
  Ethers.Contracts.UniversalSigValidator — nothing is deployed).

Invalid signatures return {:ok, false}; {:error, reason} is reserved for
malformed input and RPC transport failures, so there are deliberately no
bang variants.

Tested against anvil with a minimal ERC-1271 wallet fixture and a
CREATE2 factory fixture covering deployed-wallet and counterfactual
(ERC-6492) verification, plus EOA fast-path tests proving no RPC usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alisinabh
alisinabh force-pushed the feat/universal-sig-verification branch from 6997141 to 63c965c Compare July 19, 2026 04:37
Comment thread lib/ethers/signature.ex Outdated
Comment thread lib/ethers/signature.ex Outdated
@alisinabh
alisinabh merged commit 8dedc0d into main Jul 19, 2026
5 checks passed
@alisinabh
alisinabh deleted the feat/universal-sig-verification branch July 19, 2026 05:24
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