Cryptography and Signature Pitfalls
Smart contracts use cryptography heavily — for authentication, authorization, off-chain message verification, replay protection, ownership transfer, gasless interactions, account abstraction, and bridging. The good news is that the EVM exposes only a small set of cryptographic primitives, all well-studied. The bad news is that misusing those primitives is one of the most common and consequential bug classes in the industry. The damage from a signature bug is rarely partial: typically every signed message in the system is forgeable or replayable.
This chapter covers what an auditor needs to recognize:
ecrecoverand signature malleability. EIP-2'ss-value restriction; whyvmatters; how malleability turns into double-spend in some contract designs.- EIP-191 and EIP-712. Personal sign vs. typed-data sign; domain separation; what a "good" signed message looks like.
- Replay protection. Nonces, deadlines, chain IDs, contract addresses; the multi-axis nature of replay risk.
- Permit and Permit2. Off-chain token approvals; the common bugs around them; the Uniswap Permit2 ecosystem.
- BLS, Schnorr, and the EVM precompiles. What's available on mainnet today; common misuses; emerging patterns.
- Account abstraction signatures (ERC-4337). Validation rules, signature aggregation, paymaster signatures.
Each section assumes basic familiarity with elliptic-curve cryptography but does not require deep knowledge — the goal is to make the failure modes visible without turning the chapter into a textbook.
What an Auditor Needs to Verify About Any Signature
For any contract that verifies an off-chain signature, the audit task reduces to confirming the following hold:
- Domain separation. The signed message includes enough context that the same signature cannot be applied somewhere else (different chain, different contract, different function, different version).
- Replay protection. The signed message includes a nonce or unique identifier that, once consumed, cannot be re-used.
- Expiration. The signed message includes a
deadlinethat the contract enforces. - Malleability resistance. The signature scheme used does not admit multiple valid signatures for the same message (or, if it does, the contract treats them as a single use).
- Recovery soundness.
ecrecover(...) == expectedSigneris checked, and the contract rejectsaddress(0). - Hashing structure. The hash being signed is unambiguous: no parameter can be re-interpreted as another, no concatenation collisions are possible.
- Scheme appropriateness. The signing scheme matches the use case (ECDSA for EOA, EIP-1271 for contract wallets, account-abstraction validation for 4337).
A contract that gets all seven right is unlikely to have a signature bug. A contract that gets any of them wrong almost certainly does.
Scheme Landscape (As of 2026)
The signing schemes an auditor will encounter, by frequency:
| Scheme | Primary Use | Notes |
|---|---|---|
| ECDSA (secp256k1) | EOA signatures, the default in ecrecover | EIP-2 restricts s to low half; malleability still possible if not checked |
| EIP-191 personal_sign | Legacy "sign this message" UIs | Prefer EIP-712 for new code |
| EIP-712 typed-data | Modern standard for structured messages | Used by Permit, Permit2, most DEX intents, gasless wallets |
| EIP-1271 | Contract-wallet signature verification | Smart-contract wallets (Safe, AA) sign by calling isValidSignature |
| ERC-6492 | Pre-deployed counterfactual wallet signatures | Lets an undeployed wallet sign messages verifiably |
| secp256r1 / P-256 | Passkeys, biometric / WebAuthn devices, EIP-7212 precompile (post-Pectra) | Increasingly relevant for account abstraction |
| BLS12-381 | Aggregated signatures, ZK rollup commitments, staking signatures, EIP-2537 precompile | Used in beacon chain consensus; appearing in app-layer designs |
| Schnorr / MuSig | Multi-party signatures, emerging in DeFi | No native EVM precompile; usually verified by EVM-level math |
| EdDSA (ed25519) | Cross-chain bridges from Solana, etc.; emerging EIP for precompile | Verifier contracts on EVM today are expensive |
Most production audits in 2026 focus on ECDSA, EIP-712, EIP-1271, Permit / Permit2, and (increasingly) ERC-4337-related validation. BLS and Schnorr remain niche but worth recognizing.
A General Audit Workflow for Signed Messages
For every signature-verifying function in scope:
- Trace the off-chain construction of the message: what does the signer's wallet display? What does it actually sign?
- Identify the on-chain hash construction: what bytes are hashed before being passed to
ecrecover(or equivalent)? - Check domain separation: is the chain ID included? The contract address? A typehash unique to this function?
- Check replay protection: nonce semantics, expiration, single-use vs. multi-use logic.
- Check malleability: is
svalidated? Isvvalidated? Does the contract use OpenZeppelin'sECDSA.recover(which handles these) or rawecrecover(which does not)? - Check signer authorization: is the recovered signer the correct signer for the action being authorized?
- Check the failure mode: what happens on invalid signature? Revert is preferred; returning
falseand continuing is suspicious.
The subsections that follow expand each of these into concrete patterns and findings.