EIP-712 is the Ethereum standard for hashing and signing typed structured data, finalized on Sept 12, 2017 by Vitalik Buterin, Remco Bloemen, and Leonid Logvinov (EIPs repository). Instead of asking a wallet user to sign an opaque 32-byte hex blob, EIP-712 lets the wallet display a human-readable JSON payload, then bind that payload to a specific chain, contract, and version through a domain separator. The result is a signature that contracts can verify onchain with one ecrecover call costing 3,000 gas, while users see what they are actually authorizing. The standard now underpins ERC-20 Permit (EIP-2612), Uniswap's Permit2, Eco's Permit3, OpenSea's Seaport orders, and most gasless meta-transaction flows.
What is EIP-712 and why does it exist?
EIP-712 is an Ethereum standard that defines how to hash and sign typed structured data so wallets can display readable signature payloads and contracts can verify them cheaply. It exists because the legacy eth_sign method asked users to approve raw hex strings, which created phishing risk, replay risk across chains and contracts, and no semantic context for the signer.
Before EIP-712, the two signing methods on Ethereum were eth_sign, which signed an arbitrary 32-byte hash, and personal_sign, which prepended a fixed string to a UTF-8 message. Both showed users content that was either unreadable or trivially spoofable. A malicious dApp could ask for a signature on a hex hash that turned out to authorize a token transfer.
The standard was authored by Vitalik Buterin, Remco Bloemen, and Leonid Logvinov and moved to Final status on Sept 12, 2017 (EIPs repository). It introduced a deterministic encoding for typed objects, a domain separator that scopes signatures to a specific application, and a wallet RPC method now standardized as eth_signTypedData_v4.
How EIP-712 works: domain separator, type hashes, and the encoding pipeline
EIP-712 computes a 32-byte digest by combining three pieces: a fixed prefix 0x1901, a domain separator that binds the signature to one application, and a hash of the typed message itself. The signer's wallet displays the structured fields, signs the digest with secp256k1, and the contract recovers the address using ecrecover at the standard 3,000 gas cost (eips.ethereum.org/EIPS/eip-712).
The pipeline has four steps. First, every struct type is encoded as a string such as Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline), then hashed with keccak256 to produce a typeHash. Second, each field is encoded according to its Solidity ABI type and concatenated with the type hash, then hashed again to produce hashStruct(message).
Third, a special struct called EIP712Domain is hashed the same way. It typically contains name, version, chainId, and verifyingContract. Binding chainId and verifyingContract into the digest is what prevents a signature collected on Ethereum mainnet from being replayed on Arbitrum or against a different contract.
Fourth, the final digest is keccak256(0x1901 || domainSeparator || hashStruct(message)). The 65-byte (v, r, s) signature over that digest is what the user produces. The verifying contract recomputes the same digest from the same fields and calls ecrecover to confirm the signer. MetaMask's reference implementation lives in its signing methods documentation.
EIP-712 vs eth_sign and personal_sign: what changed for wallet UX and security
EIP-712 changed three things compared with earlier signing methods: wallets can render the actual payload as labeled fields, signatures are scoped to a specific chain and contract through the domain separator, and the structured encoding removes ambiguity about what was signed. The older methods left every protective decision to the dApp and the user's willingness to trust an opaque hash.
With eth_sign, MetaMask now shows a red warning screen because the method can sign any 32-byte value, including transaction hashes. With personal_sign, the user sees a UTF-8 string but no binding to chain or contract, so a phishing site can craft a message that looks innocuous and reuse the signature elsewhere. EIP-712 closes both gaps.
The chain binding matters most for multi-chain deployments. A USDC permit signed on Ethereum cannot be replayed against the USDC contract on Polygon, because the chainId in the domain separator differs, producing a different digest. This property is what made EIP-712 the foundation for gasless approvals across networks.
Where EIP-712 shows up today: Permit, Permit2, Permit3, OpenSea, and meta-transactions
EIP-712 is now the dominant signing path for stablecoin approvals, NFT marketplace orders, and gasless meta-transactions. EIP-2612 (the ERC-20 Permit extension) was created in March 2020, and Uniswap Labs deployed Permit2 at 0x000000000022D473030F116dDEE9F6B43aC78BA3 on Nov 17, 2022 as a universal approval router used across the DeFi stack.
USDC's EIP-2612 permit interface is the highest-volume EIP-712 signature path in stablecoin flows. With USDC at $75.6B in circulating supply and the broader stablecoin market at $315.3B as of 2026-06-05 (DeFiLlama), every permit-based deposit, lending position, or vault entry routes through an EIP-712 digest rather than a separate on-chain approve transaction.
Uniswap's Permit2 extends the pattern by holding approvals in a single canonical contract and letting any integrating protocol consume a signed transfer permission. The source contract and audit history are on github.com/Uniswap/permit2. OpenSea's Seaport protocol uses EIP-712 to express full marketplace orders, including offer items, consideration items, and zones.
Meta-transaction frameworks such as the ERC-2771 forwarder pattern rely on EIP-712 to let a relayer pay gas on behalf of an end signer. Institutional custodians including Fireblocks and Anchorage support eth_signTypedData_v4 as the signing primitive for these flows, which keeps the signer offchain while the verifying contract enforces nonce and deadline rules.
Why EIP-712 is the prerequisite for Permit2 and Permit3
EIP-712 is the prerequisite because Permit2 and Permit3 both express their authorization payloads as typed structs that the signer reviews before signing. Without the deterministic encoding and domain binding EIP-712 provides, a single signature could not safely authorize batched, cross-contract, or cross-chain token movements. The standard is what makes the orchestration layer expressible.
Permit2, authored by Uniswap Labs, uses EIP-712 typed data to authorize transfers from any token that has approved the Permit2 contract once. The user signs a PermitTransferFrom struct with a nonce, deadline, and spender, and any integrating protocol can pull the funds without a new approve call.
Permit3, authored by Eco, extends the pattern across chains. A single EIP-712 signature can authorize coordinated token movements on multiple chains, with the domain separator and witness data structured so each chain's verifying contract can confirm the same root authorization. This is the orchestration primitive institutional integrators want when they need one signing flow that spans Ethereum, Base, Arbitrum, and rollups served by Hyperlane and CCTP transport.
What can go wrong: common EIP-712 implementation pitfalls
The most common EIP-712 mistakes are an incorrect domain separator, a missing chainId, blind-signing on the wallet side, and dApps that craft typed data designed to look like one action while authorizing another. Each of these defeats the binding properties the standard provides and re-opens the phishing surface EIP-712 was designed to close.
Domain separator drift is the most frequent contract bug. If a contract caches the domain separator at deployment and never recomputes it after a chain reorg or contract migration, signatures verified after the change will fail. The OpenZeppelin EIP712 base contract handles this by recomputing the separator when the cached chainId no longer matches block.chainid.
On the wallet side, blind-signing is the dominant attack vector. Hardware wallets that cannot render the full typed payload sometimes display only the digest, which puts the user back in the eth_sign threat model. Ledger has shipped clear-signing support for specific EIP-712 schemas, and MetaMask warns when typed data fields look anomalous, but coverage is incomplete.
Malicious typed data is the third risk. A phishing dApp can present a Permit struct that looks like a benign action and authorize a transfer of the user's full token balance. Wallet reviewers now flag unbounded value fields and far-future deadline values, but final responsibility sits with the signer.
EIP-712 for institutional stablecoin flows: orchestration and settlement
For institutional stablecoin orchestration, EIP-712 is the signing primitive that lets a single authorization express intent across primary mint access, secondary market routing, and settlement. The domain separator binds each authorization to a known verifying contract, the typed struct expresses the exact terms, and the digest can be co-signed by custody policies before any onchain action.
An asset manager moving stablecoin inventory across venues does not want to run KYB with twelve different platforms or sign twelve different message formats. The institutional value proposition is one integration across markets, and EIP-712 typed data is what makes that integration legible to both compliance reviewers and verifying contracts.
For primary market mint authorizations, an issuer can accept an EIP-712-signed RFQ that names the mint contract, the chain, the amount, and the recipient, then settle once the orchestrator confirms the offchain leg. For secondary market routing, the same primitive carries best-execution data into the onchain step. Eco's role here is the neutral aggregator: assembling primary mint access, onchain liquidity, and offchain RFQ behind one orchestration surface, with Permit3 as the cross-chain signing layer built on EIP-712.
Frequently asked questions about EIP-712
Common questions about EIP-712 cover chain compatibility, backward compatibility with older signing methods, gas costs on verification, and whether the standard applies to L2s. The short answers are that EIP-712 works on every EVM chain, is not backward compatible with eth_sign, costs 3,000 gas to verify per signature, and is the default typed-data path on Ethereum L2s.
Is EIP-712 Ethereum-only? No. Any EVM-compatible chain supports it because the standard is defined at the application layer, not the consensus layer. Polygon, Arbitrum, Optimism, Base, BNB Chain, Avalanche, and Hyperliquid all accept EIP-712 signatures, and contracts on those chains verify them with the same ecrecover precompile.
Does it work on L2s? Yes, and the chainId field in the domain separator is what keeps L2 signatures isolated from mainnet. A USDC permit signed for Base will not verify on Ethereum or Arbitrum because the digest depends on the chain identifier.
Is it backward compatible with eth_sign? No. EIP-712 produces a different digest, so a signature collected via eth_sign will not verify against an EIP-712 hash and vice versa. Wallets expose eth_signTypedData_v4 as a distinct method.
What is the gas cost of ecrecover? The precompile costs 3,000 gas per signature verification and has been unchanged since the Frontier release on Jul 30, 2015 (Ethereum Yellow Paper, appendix G). That cost is what makes EIP-712 cheap enough to use as the foundation for permit-style flows in stablecoin contracts.
Methodology: Stablecoin supply figures from DeFiLlama snapshot dated 2026-06-05. EIP statuses and finalization dates from the Ethereum Foundation EIPs repository. Permit2 deployment address from Uniswap Labs GitHub. ecrecover gas cost from the Ethereum Yellow Paper, appendix G.
