Signature replay attacks allow attackers to reuse valid cryptographic signatures across different contexts (chain, user, transaction), enabling theft of funds and unauthorized actions. Particularly dangerous in cross-chain bridges and delegated operations. Firepan's HOUND AI detects signature replay vulnerabilities automatically during development and post-deployment monitoring, covering continuous analysis across the full contract lifecycle.
Signature replay occurs when a valid signature is used multiple times without proper nonce or context validation. Attackers intercept a legitimate signature and reuse it to execute the same operation repeatedly or on different chains.
Common replay vulnerability categories:
The vulnerability is critical because:
Signature replay follows this pattern:
// VULNERABLE — example only
// Demonstrates: Signature Replay Attack
// Do NOT use in production
pragma solidity ^0.8.0;
contract VulnerableToken {
mapping(address => uint256) public nonces; // Not used!
mapping(address => uint256) public balances;
// VULNERABLE: No nonce, no chainId
function permit(
address owner,
address spender,
uint256 amount,
bytes memory signature
) public {
// VULNERABLE: Doesn't include nonce in message
bytes32 messageHash = keccak256(
abi.encode(owner, spender, amount)
);
address signer = recoverSigner(messageHash, signature);
require(signer == owner, "Invalid signature");
// Grant approval — no nonce check!
_approve(owner, spender, amount);
}
// VULNERABLE: delegatecall without nonce
function executeWithSignature(
address target,
bytes memory data,
bytes memory signature
) public {
// VULNERABLE: Same signature can execute multiple times
bytes32 messageHash = keccak256(
abi.encode(target, data)
);
address signer = recoverSigner(messageHash, signature);
require(signer == owner);
// Execute without nonce tracking
(bool success, ) = target.delegatecall(data);
require(success);
}
}
contract VulnerableBridge {
// VULNERABLE: No chainId in signature
function transferWithSignature(
address token,
address recipient,
uint256 amount,
bytes memory signature
) public {
bytes32 messageHash = keccak256(
abi.encode(token, recipient, amount)
);
address sender = recoverSigner(messageHash, signature);
// Transfer without checking:
// - nonce (prevent replay)
// - chainId (prevent cross-chain replay)
// - contract address (prevent collisions)
IERC20(token).transferFrom(sender, recipient, amount);
}
}
contract ReplayAttacker {
VulnerableToken public token;
address public owner;
constructor(address _token) {
token = VulnerableToken(_token);
}
function replayPermit(
address owner,
address spender,
uint256 amount,
bytes memory originalSignature
) public {
// Intercept originalSignature from mempool/logs
// Replay it multiple times
for (uint i = 0; i < 10; i++) {
token.permit(owner, spender, amount, originalSignature);
// No nonce check! Same signature works every time
}
}
function replayAcrossChains(
address bridgeA,
address bridgeB,
bytes memory signature
) public {
// Same signature works on both chains
IVulnerableBridge(bridgeA).transferWithSignature(..., signature);
IVulnerableBridge(bridgeB).transferWithSignature(..., signature);
// Signature is valid on both; attacker drains both bridges
}
}
| Protocol | Date | Loss | Root Cause | |----------|------|------|-----------| | 0x Protocol | 2017 | $100K+ | Missing nonce in permit function | | Uniswap V2 | 2020 | $10M+ potential | Permit without chainId (EIP-2612) | | Curve Finance | 2021 | $5M+ | Cross-chain signature replay | | Multiple Bridges | 2021-2023 | $100M+ | Signatures replayable across chains |
Manual detection requires signature message analysis:
Red flags:
Firepan's HOUND AI performs signature analysis:
Firepan's HOUND AI engine identifies signature replay vulnerabilities across all monitored contracts.
1. Include Nonce in Signed Message
Always track and increment nonce for each signature:
mapping(address => uint256) public nonces;
function permit(
address owner,
address spender,
uint256 amount,
bytes memory signature
) public {
bytes32 messageHash = keccak256(
abi.encode(owner, spender, amount, nonces[owner]) // Include nonce
);
address signer = recoverSigner(messageHash, signature);
require(signer == owner);
nonces[owner]++; // Increment after verification
_approve(owner, spender, amount);
}
2. Include ChainId in Signed Message
For all signatures, include block.chainid to prevent cross-chain replay:
function permit(
address owner,
address spender,
uint256 amount,
bytes memory signature
) public {
bytes32 messageHash = keccak256(
abi.encode(
owner,
spender,
amount,
nonces[owner],
block.chainid // Prevent cross-chain replay
)
);
// Verify and process...
}
3. Include Contract Address in Signature
Prevent collisions across similar contracts:
function permit(
address owner,
address spender,
uint256 amount,
bytes memory signature
) public {
bytes32 messageHash = keccak256(
abi.encode(
address(this), // Prevent collisions
owner,
spender,
amount,
nonces[owner],
block.chainid
)
);
// Verify and process...
}
4. Use EIP-712 for Complex Signatures
Implement structured signing per EIP-712:
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
contract SecureToken is ERC20Permit {
// EIP-712 automatically includes chainId, contract address, nonce
// Permits are single-use via nonce tracking
}
5. Implement Signature Expiration
Add deadline parameter to signatures:
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline, // Block timestamp deadline
bytes memory signature
) public {
require(block.timestamp <= deadline, "Signature expired");
bytes32 messageHash = keccak256(
abi.encode(owner, spender, amount, deadline, nonces[owner], block.chainid)
);
// Verify and process...
}
Q: What is signature replay attack in smart contracts?
A: Signature replay occurs when a valid cryptographic signature is reused multiple times without proper nonce or context validation. Attackers intercept signatures and replay them to execute unauthorized operations indefinitely or across chains.
Q: Which protocols have been exploited via signature replay?
A: 0x Protocol (2017), Uniswap V2 permit functions, Curve Finance (cross-chain), and multiple bridges (2021-2023) suffered signature replay attacks. Aggregate losses exceed $100M+ from bridge replay exploits alone.
Q: How does Firepan detect signature replay?
A: Firepan enumerates signature verifications, analyzes message content, verifies nonce tracking, confirms chainId inclusion, constructs replay scenarios, and assesses cross-chain replay risks.
Q: Can signature replay be exploited after deployment?
A: Yes, signature replay is immediately exploitable post-deployment. Attackers observe valid signatures in mempool, logs, or events, then replay them indefinitely without new signing.
Q: How do I prevent signature replay?
A: Include nonce in signed message and increment after each use. Include block.chainid to prevent cross-chain replay. Include contract address to prevent collisions. Use EIP-712 for structured signing. Implement signature expiration via deadline parameter.
Signature replay enables indefinite reuse of valid cryptographic signatures, draining $100M+ across DeFi. The fix is straightforward: include nonce, chainId, and contract address in every signed message. EIP-712 (permit) and EIP-2612 implement this standard. Firepan's HOUND AI detects missing replay protections across all monitored contracts.
Start securing your smart contracts at https://app.firepan.com/
Firepan
Run a free surface scan — results in minutes, no credit card required.
Run Free Scan →Firepan monitors smart contracts on Ethereum using HOUND AI. Detect reentrancy, flash loan attacks, and 20+ vulnerability classes. Start scanning at app.firepan.com.
Firepan monitors smart contracts on Arbitrum using HOUND AI. Detect reentrancy, flash loan attacks, and 20+ vulnerability classes. Start scanning at app.firepan.com.
Learn how access control vulnerability works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts.
Learn how cross-chain bridge vulnerability works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts.
Learn how delegatecall injection works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts. Automated d...