Skip to main content
Sigvex

Permit Vulnerabilities

Detects ERC-2612 permit implementation issues including front-running, nonce manipulation, and deadline bypass.

Permit Vulnerabilities

Overview

The permit vulnerability detector identifies issues in ERC-2612 permit() implementations and their usage. The permit function allows gasless approvals via off-chain signatures, but introduces vulnerabilities including front-running of permit transactions, nonce desynchronization, and missing deadline enforcement.

Why This Is an Issue

Permit signatures can be:

  • Front-run: An attacker observes a pending permit transaction and submits it first, potentially in a context that benefits them (e.g., before a transferFrom).
  • Replayed: If nonce handling is incorrect, the same permit signature can be used multiple times.
  • Stolen: Permit signatures are valid until the deadline; if leaked, they can be used by anyone before expiry.

Protocols that combine permit + transferFrom in separate transactions are particularly vulnerable, as the permit can be front-run and the approval redirected.

Findings carry high severity overall, but the per-issue rating varies with what is missing: a missing signature verification is critical, missing nonce, deadline, chain-ID, or zero-address checks are high, and a weak (non-strict) deadline comparison is medium.

How to Resolve

// Before: Separate permit and transfer -- front-runnable
function depositWithPermit(uint256 amount, uint8 v, bytes32 r, bytes32 s) external {
    token.permit(msg.sender, address(this), amount, deadline, v, r, s);
    token.transferFrom(msg.sender, address(this), amount);
}

// After: Atomic permit+transfer with try/catch for already-permitted
function depositWithPermit(uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external {
    try token.permit(msg.sender, address(this), amount, deadline, v, r, s) {} catch {
        // permit may have already been front-run -- check allowance
        require(token.allowance(msg.sender, address(this)) >= amount, "Insufficient allowance");
    }
    token.transferFrom(msg.sender, address(this), amount);
}

Examples

Sample Sigvex Output

{
  "detector_id": "permit-vulnerabilities",
  "severity": "high",
  "confidence": 0.70,
  "description": "permit() call at offset 0x48 followed by transferFrom() at offset 0x7c. If the permit is front-run and the approval is consumed by another contract, the transferFrom will fail, causing DoS.",
  "location": { "function": "depositWithPermit(uint256,uint8,bytes32,bytes32)", "offset": 72 }
}

Detection Methodology

  1. Permit call detection: Identifies calls with the permit selector (ERC-2612).
  2. Atomicity check: Verifies whether permit and transferFrom occur atomically or can be separated.
  3. Error handling: Checks for try/catch around permit calls to handle front-running gracefully.
  4. Deadline validation: Ensures deadline parameter is checked and not set to type(uint256).max.

Limitations

  • Off-chain permit signature leakage is not detectable at the bytecode level.
  • DAI-style non-standard permit implementations may not be recognized.

References