Understanding EIP-712; Secure and Readable Signed Messages
EIP-712 improves Ethereum message signing by introducing a structured, human-readable format that enhances security and usability compared to EIP-191, which relies on raw message hashes. By encoding messages with a defined schema, EIP-712 allows wallets to display clear signing requests, reducing phishing risks and preventing blind approvals. Key security benefits include domain separation to prevent replay attacks, input validation to ensure correct data, and expiration timestamps to limit signature reuse. Proper implementation, including strong domain separators and user-friendly wallet interfaces, ensures that EIP-712 remains a secure and transparent standard for Ethereum transactions.

Comparing EIP-191 and EIP-712
1. EIP-191: Simple Message Signing
EIP-191 defines a generic way to sign messages in Ethereum. It involves signing a raw message hash prefixed with Ethereum Signed Message:
, ensuring that the signature cannot be directly used as a transaction. However, this method lacks structure, making it difficult for users to verify what they are signing. This can lead to security risks such as blind approvals and phishing attacks.
2. EIP-712: Structured Data Signing
EIP-712 improves upon EIP-191 by introducing a structured format for signing messages using Typed Data. Instead of a simple hash, messages are encoded with a defined schema, enabling wallets to present a clear and human-readable signing request to users. This reduces confusion and enhances security by making signed data more understandable.
3. Security and UX Enhancements
While EIP-191 is still widely used for basic signing, EIP-712 provides significant security and usability benefits:
- Human-Readable Data: Users can see exactly what they are signing instead of a raw hash.
- Domain Separation: Each signature is tied to a specific domain, preventing replay attacks across different applications.
- Improved Wallet Support: Wallets like MetaMask can parse and display structured data, ensuring transparency in transactions.
How to Implement EIP-712 Securely
While EIP-712 significantly improves security, improper implementation can still lead to vulnerabilities. Here are best practices for making EIP-712-based signing more secure:
1. Validate User Input Properly
Ensure that the signed data matches the expected schema. Incorrect or missing validation can lead to unintended transactions.
2. Use a Strong Domain Separator
Each EIP-712 message includes a domain separator, which should be unique to the application. This prevents cross-domain replay attacks. The domain separator should include:
- A unique name for your application
- The current chain ID
- A version identifier
- The contract address
3. Restrict Expiry Time on Signatures
Including an expiry time in signed messages ensures that signatures cannot be reused indefinitely, reducing the risk of replay attacks. By adding a timestamp or deadline field, developers can limit the validity of a signature, preventing attackers from submitting old, previously signed messages at a later time.
4. Example of a Safe vs. Unsafe signing request
Unsafe Signing (Raw Message Signing – Risky)
A malicious dApp might trick users into signing a raw message like this:
Sign this message to verify your identity:
0x4f3c2a9b8e... (random-looking data)
Since raw messages provide no context, users might unknowingly sign a transaction approval disguised as an identity verification request. Attackers can then use this signature to drain funds or execute unauthorized actions.
Safe Signing (EIP-712 Structured Data – Secure)
Instead, using EIP-712, the signing request clearly defines what the user is approving:
{
"types": {
"Permit": [
{ "name": "owner", "type": "address" },
{ "name": "spender", "type": "address" },
{ "name": "value", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" }
]
},
"domain": {
"name": "SecureToken",
"version": "1",
"chainId": 1,
"verifyingContract": "0x123456..."
},
"message": {
"owner": "0xUserAddress",
"spender": "0xSpenderAddress",
"value": "1000000000000000000",
"nonce": 1,
"deadline": 1710000000
}
}
Here, the wallet will display clear, structured information showing that the user is granting a specific allowance to a spender. This prevents phishing attempts where users sign messages without knowing their true effect.
5. Leverage Wallet Warnings and UI Enhancements
Encourage users to verify the structured message before signing. Wallets should display clear warnings when interacting with unknown contracts.
Conclusion
EIP-712 is a game-changer for Ethereum's security and usability, providing structured, human-readable message signing. However, developers must implement it carefully to avoid new attack vectors. By enforcing domain separation, input validation, expiry mechanisms, and clear wallet UIs, EIP-712 can significantly reduce phishing risks and improve user trust.