CCamoCrypt camocrypt.com
Security

What Is EIP-712 Signing?

EIP-712 replaced signing an unreadable hex blob with structured, human-readable data. It is a safety upgrade, but not a substitute for reading.

Quick answer

EIP-712 is an Ethereum standard for hashing and signing typed, structured data so your wallet can display a readable message instead of an opaque hex string. It binds each signature to a specific application through a domain separator that includes the chain, contract, and version. That readability improves safety, but attackers still abuse EIP-712 for signature phishing, so you must read what you sign.

Key points

  • EIP-712 lets wallets show human-readable, structured data instead of a raw 32-byte hash when you sign.
  • A domain separator binds each signature to a specific name, version, chain ID, and contract, preventing cross-app and cross-chain replay.
  • The signed digest is built from the 0x1901 prefix, the domain separator, and a hash of the typed message.
  • It underpins gasless approvals like ERC-2612 Permit and Permit2, which is exactly why attackers abuse it.
  • Readable does not mean safe: a legible message can still authorize theft if you approve it blindly.
  • Always check the domain contract, the message contents, and what the signature actually authorizes.

Every time you interact with a decentralized application, you may be asked to sign something. For years, that request often appeared as an unreadable string of hexadecimal characters, and users learned to click approve without understanding what they were authorizing. That habit was a security disaster. EIP-712 is the Ethereum standard designed to fix it by making signed data human-readable and cryptographically scoped to a specific application. It is one of the most important safety improvements in everyday wallet use, and also one of the most misunderstood, because readable is not the same as safe.

The problem EIP-712 solves

Ethereum lets applications ask you to sign off-chain messages, which are useful for gasless approvals, order books, and meta-transactions. The trouble was presentation. A structured request was typically hashed and shown to the user as an opaque 32-byte blob. You could not tell whether you were authorizing a harmless login or handing a contract permission to move your tokens. The official EIP-712 specification frames its purpose directly: it enables users to verify what they are actually signing, rather than approving data they cannot interpret. If you are new to what these approvals even do, what a smart contract is and isn’t provides useful background.

What EIP-712 does

EIP-712, titled “Typed structured data hashing and signing,” defines two things: a deterministic way to encode typed data so it can be hashed consistently, and a way to bind that data to a specific application so a signature cannot be reused where it was not intended. The result is that a wallet can display fields such as a spender, an amount, and a deadline in plain terms, then produce a signature a smart contract can verify on-chain. The standardized wallet method for this is eth_signTypedData, currently in its v4 form.

The domain separator

The heart of EIP-712’s safety model is the domain separator. Its job, in the specification’s words, is to prevent “collision of otherwise identical structures” so a signature meant for one application cannot be replayed against another. It is computed from a set of domain fields:

  • name: the human-readable name of the application or protocol.
  • version: the version of the signing domain.
  • chainId: the chain the signature is valid on, which prevents cross-chain replay.
  • verifyingContract: the contract expected to verify the signature, which enables wallets to perform contract-specific phishing checks.
  • salt: an optional last-resort disambiguator.

These fields are why an EIP-712 signature is scoped rather than universal. A signature you produce for one app on one chain is meaningless elsewhere, which shuts down entire classes of replay attacks.

How the digest is built

Under the hood, EIP-712 assembles the value you actually sign from three parts. The specification defines the encoding as the bytes 0x19 0x01, followed by the domain separator, followed by a hash of the message structure. In the standard’s notation this is "x19x01" ‖ domainSeparator ‖ hashStruct(message).

The 0x1901 prefix is not decorative. It keeps EIP-712 signatures compatible with the ERC-191 signing scheme and prevents a signed message from being interpreted as a regular Ethereum transaction. The message portion is hashed deterministically: each type gets a typeHash derived from its encoded type string, and the values are hashed alongside it. This determinism is what lets a contract independently recompute the same digest and verify your signature. To see how signed and on-chain data surfaces in practice, how to read a block explorer is a helpful companion.

The specification’s own illustrative example shows how legible the encoded type becomes. A simple message type is expressed as a plain, human-parseable string:

Mail(address from,address to,string contents)

That string is hashed to produce the typeHash, and the wallet can present the corresponding fields, from, to, and contents, as labeled values rather than as raw bytes. When you extend this idea to a token approval, the readable fields become the spender, the value, and the deadline, which is exactly the information you need to judge whether a request is safe.

How it compares to older signing methods

EIP-712 did not appear in a vacuum; it replaced cruder signing methods that were actively dangerous:

  • eth_sign signs an arbitrary 32-byte hash with no context at all. Because it can be made to sign the hash of a real transaction, wallets now warn heavily against it, and many disable it by default.
  • personal_sign (ERC-191) improved matters by prefixing a human-readable string, which is fine for simple login-style messages but cannot express structured data or bind a signature to a specific contract and chain.
  • eth_signTypedData_v4 (EIP-712) adds typed, structured fields plus the domain separator, giving both readability and scoping.

If a site ever asks you to use eth_sign, or presents a bare hash with a warning, treat that as a serious red flag and refuse. The move toward EIP-712 exists precisely to retire that kind of blind signing.

Where you encounter it

EIP-712 is now foundational infrastructure. It underpins ERC-2612 Permit, which lets you approve a token spend by signing a message instead of sending a transaction; Uniswap’s Permit2; NFT marketplace orders; and most gasless meta-transaction flows. Each of these relies on the fact that a signed, typed message can carry the same authority as a transaction. That power is precisely why EIP-712 is a favorite tool of attackers, connecting directly to signature phishing involving Permit, approve, and setApprovalForAll.

The appeal to legitimate applications is real: gasless approvals improve user experience, because you can authorize an action with a signature and let the application submit the transaction and pay the gas. Off-chain orders let marketplaces match trades without every bid touching the chain. Meta-transactions let newcomers act before they hold any native token for fees. In each case, EIP-712 provides the structured, verifiable, scoped signature that makes the pattern safe to build on. The same properties that make it useful to builders, however, mean a single careless signature can be as consequential as sending funds directly.

Readable does not mean safe

This is the critical point. EIP-712 makes signature requests legible, but legibility only helps if you read and understand them. A malicious site can present a perfectly valid, perfectly readable EIP-712 message that, if approved, grants a spender unlimited permission over your tokens. The wallet is showing you the truth; the danger is that the truth is a request you should refuse. This is a common step in how wallet drainers work: the victim approves a real, well-formed signature that authorizes their own losses.

So treat every EIP-712 prompt as a contract you are agreeing to:

  • Check the domain. Does the name and verifyingContract match the application you actually opened? A mismatch is a red flag.
  • Check the chain. Confirm the chainId is the network you intend to use.
  • Read the message fields. For Permit-style requests, look at the spender address and the amount. An unlimited amount to an unfamiliar spender is a reason to stop.
  • Match intent. If you came to mint, claim, or log in, a request to grant token-spending authority does not fit and should be rejected.

Modern wallets increasingly help with this by decoding EIP-712 messages into plain descriptions and, in some cases, simulating the outcome of a signature before you approve it. Treat those aids as valuable but not infallible. A decoded description tells you what the message says; it does not judge whether the spender deserves your trust. The wallet cannot know that a contract address is malicious, only that it is the one named in the request. The final judgment, does this application, on this chain, need this permission, remains yours.

Cleaning up after signing

Because EIP-712 Permit signatures can create spending allowances, they belong in your periodic security review. If you have approved Permit-style requests, verify and clear anything you do not recognize; the process is covered in how to revoke token approvals. Building this into a routine ensures that even a signature you later regret does not remain an open door. Keep in mind that a Permit signature can create an allowance without ever appearing as an obvious on-chain approval you initiated, so a periodic review of active allowances is the only reliable way to catch one that slipped through in the moment.

The bottom line

EIP-712 is a genuine and important safety upgrade. It replaced blind approval of opaque hashes with structured, scoped, human-readable data, and it gives both wallets and contracts the tools to detect misuse. But it shifts responsibility rather than removing it. The standard makes the truth visible; whether you act on that truth is up to you. Understand the domain separator, respect that a signature can carry a transaction’s power, and read every typed message before you approve it. That combination, a good standard plus an attentive user, is what real security looks like. No standard can make an unread approval safe, and no wallet warning can substitute for the moment you pause to ask whether this request matches what you actually came to do.

Sources

Frequently asked questions

What problem does EIP-712 solve?
Before EIP-712, signing a structured request often meant approving an opaque hexadecimal hash you could not interpret. EIP-712 defines a deterministic way to encode typed data so wallets can display it as readable fields. As the specification puts it, it enables users to verify what they are signing, closing a major gap that made blind approval the norm.
What is the domain separator?
The domain separator scopes a signature to one application so it cannot be replayed elsewhere. It is built from fields including the app name, a version, the chain ID, and the verifying contract address. The chain ID blocks cross-chain replay, and the contract address lets wallets perform contract-specific phishing checks.
Is a message signature safer than a transaction?
Not automatically. EIP-712 makes structured signatures readable, which helps, but certain typed messages such as an ERC-2612 Permit grant spending power without an on-chain transaction. A signature can be as consequential as a transaction, so the safety comes from reading and understanding it, not from it being a signature.
How does EIP-712 relate to phishing?
It cuts both ways. Readable data helps you catch a malicious request, and the domain's verifying contract enables phishing checks. But scammers craft legitimate-looking EIP-712 messages, often Permit or Permit2 approvals, that authorize draining your tokens. The standard improves visibility; it does not remove the need for caution.
What is the 0x1901 prefix?
The signed digest begins with the two bytes 0x19 0x01. This prefix keeps EIP-712 signatures compatible with the broader ERC-191 signing scheme and, crucially, prevents a signed message from being mistaken for a regular Ethereum transaction. The full digest is that prefix, then the domain separator, then the hash of the message.
What should I check before approving an EIP-712 request?
Confirm the domain name and verifying contract match the application you are actually using, verify the chain is correct, and read the message fields to understand what you authorize, especially spender addresses and amounts in Permit-style requests. If anything is unfamiliar or the amount is unlimited, reject it and investigate.

Note: CamoCrypt is security & education only — no prices, no predictions, no investment advice. Verify every address and contract yourself; we cannot recover lost funds and neither can anyone who contacts you claiming they can.