# signature replay attacks succeed when contracts verify signatures without tracking processed message hashes
When a contract verifies a signature but does not record which message hashes have been processed, the same signed message can be submitted repeatedly. Three defense mechanisms exist: tracking processed hashes in a mapping, including the contract address in the signed data (preventing cross-contract replay), and including a nonce (preventing same-contract replay).
Since [[signature malleability allows replay by computing complementary ECDSA signatures without the private key]], even tracking raw signatures is insufficient; the signed hash itself must be tracked. EIP-712 provides standardized structured signature data including chain ID and contract address. Since [[abi.encodePacked concatenates types shorter than 32 bytes without padding creating collision risks]], packed encoding in signed messages allows attackers to craft different inputs producing the same hash.
A broader heuristic applies beyond signatures: for every function, ask whether repeated calls with the same parameters should be possible. If not, verify safeguards exist. This generalizes replay protection beyond cryptographic signatures to general function idempotency (e.g., reward claims, configuration setters, oracle submissions).
Five sub-patterns cover the full replay attack surface:
1. **Cross-chain replay**: signing without `chain_id`; replays on any chain with the same contract address. See [[cross-chain signature replay succeeds when UserOperations omit chain_id from the signed message]].
2. **Missing parameter binding**: omitted parameters let a replayer substitute values while keeping the signature valid.
3. **No expiration deadline**: signatures without timestamps function as permanent authorizations. See [[signature expiration deadlines are necessary because signatures without timestamps function as irrevocable lifetime licenses]].
4. **Signature malleability**: `ecrecover()` accepts both canonical and non-canonical signatures. Use OpenZeppelin's ECDSA library to normalize.
5. **Missing nonce tracking**: the nonce must be both included in the signed data and invalidated on use.
---
Relevant Notes:
- [[signature malleability allows replay by computing complementary ECDSA signatures without the private key]]: one mechanism enabling replay (sub-pattern 4 in the taxonomy above)
- [[cross-chain signature replay succeeds when UserOperations omit chain_id from the signed message]]: concrete Account Abstraction case for sub-pattern 1 (cross-chain replay)
- [[signature expiration deadlines are necessary because signatures without timestamps function as irrevocable lifetime licenses]]: detailed expansion of sub-pattern 3 (no expiration)
- [[ecrecover returns address zero on invalid signatures which matches uninitialized address variables creating false authorization]]: another signature verification failure mode
- [[abi.encodePacked concatenates types shorter than 32 bytes without padding creating collision risks]]: packed encoding in signed message construction enables hash collision attacks
Topics:
- [[vulnerability-patterns]]