ERC-1271 Signature Verification
Detects insecure ERC-1271 contract signature verification including missing magic value checks, reentrancy during verification, and gas griefing.
ERC-1271 Signature Verification
Overview
The ERC-1271 detector identifies vulnerabilities in contract signature verification. ERC-1271 allows smart contracts (multisigs, smart accounts) to validate signatures by implementing isValidSignature(bytes32, bytes). Callers that verify signatures must check for contract signers and call this function, but common mistakes include not checking the return magic value, allowing reentrancy during verification, or assuming all signers are EOAs.
Why This Is an Issue
Flawed ERC-1271 verification allows:
- Signature forgery: If the caller does not check the 0x1626ba7e magic value, any contract can claim any signature is valid.
- Reentrancy: The
isValidSignaturecall is an external call to a potentially malicious contract, creating a reentrancy vector. - Gas griefing: A malicious signer contract can consume all available gas in
isValidSignature, causing the verification to fail. - EOA-only assumption: Code that uses
ecrecoverwithout falling back to ERC-1271 excludes smart contract wallets.
How to Resolve
// Before: Only supports EOA signatures
function verify(bytes32 hash, bytes memory sig, address signer) internal view returns (bool) {
return ECDSA.recover(hash, sig) == signer; // Fails for contract wallets
}
// After: Supports both EOA and ERC-1271
function verify(bytes32 hash, bytes memory sig, address signer) internal view returns (bool) {
if (signer.code.length > 0) {
// Contract signer -- use ERC-1271
try IERC1271(signer).isValidSignature(hash, sig) returns (bytes4 magic) {
return magic == IERC1271.isValidSignature.selector;
} catch {
return false;
}
} else {
// EOA signer
return ECDSA.recover(hash, sig) == signer;
}
}
Examples
Sample Sigvex Output
{
"detector_id": "erc1271-signature",
"severity": "high",
"confidence": 0.78,
"description": "Signature verification at offset 0x5a calls isValidSignature() but does not check for the 0x1626ba7e magic return value. Any contract returning non-reverting data will pass verification.",
"location": { "function": "verify(bytes32,bytes,address)", "offset": 90 }
}
Detection Methodology
- ERC-1271 call detection: Identifies calls with the
isValidSignatureselector (0x1626ba7e). - Return value check: Verifies that the caller compares the return value against the expected magic value.
- Fallback analysis: Checks whether ECDSA recovery is attempted first or whether the caller supports both EOA and contract signers.
- Reentrancy context: Evaluates whether state changes occur before or after the
isValidSignatureexternal call.
Limitations
- Cannot verify that the called contract’s
isValidSignatureimplementation is secure. - Gas limits on the
isValidSignaturecall may mitigate griefing but are hard to detect statically.
Related Detectors
- Signature Verification — general signature verification issues
- Signature Malleability — ECDSA signature malleability
- Account Abstraction — ERC-4337 issues