All Guides
Smart ContractsEIP-712Signatures

EIP-712: How Structured Data Signing Works

What EIP-712 is, how structured data signing enables gasless approvals and off-chain order books, and how to implement it correctly.

Updated March 7, 2026 8 min read

EIP-712 defines the standard for structured, human-readable data signing on Ethereum. It's what enables gasless ERC-20 approvals (permit), off-chain order books like OpenSea and Uniswap, and meta-transactions.

The Problem EIP-712 Solves

Before EIP-712, when a dApp asked users to sign a message, wallets displayed a raw hex string — completely unreadable. This was a significant security risk: users couldn't verify what they were signing. Phishing sites exploited this by asking users to sign messages that were actually malicious transactions.

How EIP-712 Works

EIP-712 defines a standard for typing signed data. The signer's wallet displays structured, human-readable information: the domain (contract address, chain ID), the type structure, and the field values. Users can verify they're signing exactly what they intend before approving.

Domain Separator

Every EIP-712 signature includes a domain separator — a hash of the contract name, version, chain ID, and contract address. This prevents signature replay attacks: a signature created for Contract A on Ethereum mainnet is invalid for Contract B or on a different chain. Always include chain ID in your domain separator.

ERC-20 Permit

ERC-2612 (permit) uses EIP-712 to enable gasless ERC-20 approvals. Instead of spending gas on an approval transaction, users sign an EIP-712 message off-chain. The spender (e.g., a DEX) submits the signature on-chain along with the actual operation. One transaction instead of two. Used extensively in DeFi — Uniswap, Aave, DAI all support permit.

Off-Chain Order Books

OpenSea's seaport protocol uses EIP-712 signed orders. A seller signs an order (token ID, price, expiry) off-chain. No gas until the order is filled. The buyer submits the transaction with the seller's signature, and the contract verifies it. This is how OpenSea can show thousands of listings without each listing costing gas.

Implementation

Use OpenZeppelin's EIP712.sol as the base. Define your type hash (keccak256 of your type string). Implement the _hashTypedDataV4(bytes32 structHash) function. Verify signatures with ECDSA.recover(). Never implement EIP-712 from scratch — use the audited library. Common mistakes: wrong type string ordering, forgetting chain ID in the domain, not checking signature expiry.

Security Considerations

Always verify the domain separator matches the intended contract and chain. Check for signature expiry (include a deadline field). Use nonces to prevent signature replay within the same domain. Be careful with signature malleability — use OpenZeppelin's ECDSA library which handles this.

Ready to build your Web3 project?

Tell us about your project and get a precise quote.

Get a Project Quote