Skip to main content
Sigvex

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 isValidSignature call 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 ecrecover without 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

  1. ERC-1271 call detection: Identifies calls with the isValidSignature selector (0x1626ba7e).
  2. Return value check: Verifies that the caller compares the return value against the expected magic value.
  3. Fallback analysis: Checks whether ECDSA recovery is attempted first or whether the caller supports both EOA and contract signers.
  4. Reentrancy context: Evaluates whether state changes occur before or after the isValidSignature external call.

Limitations

  • Cannot verify that the called contract’s isValidSignature implementation is secure.
  • Gas limits on the isValidSignature call may mitigate griefing but are hard to detect statically.

References