A signature that authorizes one transfer can be used to authorize it again. A signature valid on Ethereum can work on every EVM chain with the same contract address. Without nonces, chain IDs, and contract addresses in your signed message, every signature you issue is a standing authorization.
When a user signs a message off-chain, your contract verifies the signature with ecrecover() to confirm who authorized the action. If the message doesn't include a nonce (to prevent reuse), the chain ID (to prevent cross-chain replay), and the contract address (to prevent replay on a different contract), an attacker can take that one valid signature and use it as many times as they want, on any chain, on any contract with the same interface.
permit() function implementations missing domain separatorA signature replay attack occurs when a valid signed message (like an authorization to transfer tokens) can be reused multiple times after the original use — either on the same contract, on a different deployed instance of the same contract, or across a chain fork. The contract accepts the signature as valid each time because it doesn't track which signatures have already been used.
Step 1: A user signs a message authorizing action X (e.g., 'transfer 100 USDC to Alice'). Step 2: An attacker captures this signature. Step 3: The attacker submits the same signature again — either before the contract marks it used, or on a different instance of the contract. Step 4: The action executes again, draining funds or duplicating the authorized operation.
Three defenses: (1) Nonces — include a unique nonce in each signed message and track used nonces in a mapping. (2) Deadlines — include an expiry timestamp in signatures so they can't be reused after a certain time. (3) Chain ID and contract address — include these in the signed data (EIP-712 standard does this automatically) so signatures are invalid on other chains or contract instances.
Yes. The Wintermute hack ($20M, 2022) and several cross-chain bridge exploits involved replay attacks across different chain deployments. Many ERC-20 `permit()` implementations without proper nonce tracking have been drained. Cross-chain replay became a major concern during the Ethereum/Ethereum Classic split and EIP-155 was adopted specifically to prevent it.
EIP-712 is a standard for structured data signing that encodes the chain ID, contract address (verifying contract), and domain separator into every signature. This makes signatures invalid on other chains or contracts even if the payload is identical. Most modern signature verification in DeFi uses EIP-712. SmartContractAuditor.ai checks whether your signature verification follows EIP-712 or is vulnerable to replay.