← ClaudeAtlas

signature-replaylisted

Detect signature-replay, EIP-712 / EIP-2612 mistakes, malleable signatures, cross-chain replay, missing nonces. Activate on `ecrecover`, `permit`, meta-transactions, signed orders, signed approvals, EIP-712 domain construction, gasless transaction relayers.
iktok90-design/ai-smart-contract-auditor · ★ 36 · AI & Automation · score 80
Install: claude install-skill iktok90-design/ai-smart-contract-auditor
# Signature replay & EIP-712 detection ## When this applies - `ecrecover` and any signature verification path - `permit` (EIP-2612, ERC-4494) implementations - Meta-tx / gasless flows (ERC-2771, EIP-3074 / EIP-7702 wrapping) - Signed off-chain orders (0x, Seaport, custom) - Signed governance votes - Validator-set / bridge signature aggregation (see [[bridge-specialist]]) ## Detection patterns ### Missing nonce (CRITICAL) ```solidity bytes32 digest = keccak256(abi.encode(sender, amount)); // ← no nonce, infinitely replayable require(ecrecover(digest, v, r, s) == sender); ``` ### Missing chainId in domain (CRITICAL — cross-chain replay) EIP-712 domain MUST include `chainId`. Without it, signing on Ethereum replays on Optimism/Arbitrum/etc. ```solidity bytes32 domain = keccak256(abi.encode(EIP712_DOMAIN, name, version, /* no chainId */ , verifyingContract)); ``` ### Hardcoded chainId / `_DOMAIN_SEPARATOR` cached without fork-detect (HIGH) ```solidity DOMAIN_SEPARATOR = _hashDomain(block.chainid); // ← cached in constructor, breaks after fork ``` Re-compute when `block.chainid` differs. ### Signature malleability (HIGH) ECDSA accepts both `(r, s)` and `(r, n-s)` for valid signatures. If you use the digest as a uniqueness key, attacker can flip s and replay. Enforce `s ≤ secp256k1n/2` and `v ∈ {27, 28}`. Or use OpenZeppelin's `ECDSA.tryRecover` which already does this. ### `ecrecover` returns address(0) on invalid sig — not reverted (HIGH) ```solidity address signer =