中文
Uncategorized

EIP-712 Typed Structured Signatures in Practice: Defending Against Web3 Phishing & Unauthorized Drains

Jacky Wang 3 分钟阅读 6 阅读

As autonomous AI agents, intent-centric protocols, and account abstraction wallets interact with on-chain liquidity, the execution layer is shifting from raw transactions to off-chain signed messages. However, off-chain signatures remain the number one attack vector for wallet drainers and phishing exploits.

This technical guide dissects EIP-712 (Typed Structured Data Hashing and Signing) from an auditor’s perspective: how it prevents blind signing, where implementation vulnerabilities hide, and how developers can build bulletproof signature verification pipelines.

1. The Problem with Blind Signing: Why eth_sign Failed

In early Ethereum dApps, off-chain messages used eth_sign, which accepted arbitrary hexadecimal bytes. Attackers presented unsuspecting users with an opaque hash string (e.g., 0x4a9f...). Once signed, the attacker could wrap that signature into a malicious smart contract call to drain all tokens.

EIP-712 solved this by establishing a standardized JSON-schema-like format that crypto wallets can decode into human-readable parameters: the exact spender, amount, nonce, expiration timestamp, and contract address.

2. The Architecture of EIP-712: Domain Separators & Struct Hashes

An EIP-712 digest consists of two cryptographic building blocks combined via keccak256:

// The final digest to be passed to ecrecover
bytes32 digest = keccak256(
    abi.encodePacked(
        "",
        DOMAIN_SEPARATOR,
        hashStruct(message)
    )
);

(1) The Domain Separator (Cross-Chain & Cross-Contract Replay Defense)

The domain separator binds the signature to a specific application context:

  • name: The name of the protocol (e.g., “Uniswap”).
  • version: The signing domain version.
  • chainId: Prevents signatures on Ethereum Mainnet from being replayed on Arbitrum, Optimism, or Polygon.
  • verifyingContract: Restricts the signature exclusively to the target contract instance.

(2) TypeHash & HashStruct

The message structure is encoded using deterministic type hashes, ensuring that neither parameters nor data types can be tampered with.

3. Dangerous Pitfalls in Modern Implementation

  1. Cached DOMAIN_SEPARATOR during Hard Forks: Caching the domain separator in an immutable variable without checking block.chainid leaves the contract vulnerable to replay attacks after network hard forks. Production contracts must dynamically reconstruct the domain separator if the current chainId changes.
  2. Overly Permissive Permit Deadlines: When integrating ERC-2612 Permit, setting deadline = type(uint256).max allows signatures to remain valid indefinitely in mempools, exposing users to sandwich attacks or delayed exploits. Always enforce strict, bounded expirations (e.g., 10 to 15 minutes).
  3. Signature Malleability in ecrecover: Raw ecrecover accepts non-canonical elliptic curve s and v values. Always use audited libraries like OpenZeppelin’s ECDSA.recover to enforce s <= secp256k1_order / 2.

Summary

EIP-712 is a foundational primitive for intent-centric dApps and automated agent transactions. Correct domain separation, bounded expiration deadlines, and robust signature verification libraries are essential to keep user assets safe.

发表评论