EIP-712 Domain Mismatch: Should You Sign Such Requests?

 / 
2

Never sign an EIP-712 request when the domain is inconsistent. This isn't being pedantic—it's how EIP-712 security works: the chainId and verifyingContract fields in the Domain are meant to prevent signatures from being replayed across chains and contracts. A mismatch means the signature could be used elsewhere.

OKX Exchange
A leading global cryptocurrency platform,suitable for both beginners and experienced traders.
New user benefit: 20% off trading fees upon registration!!

1. First, understand what the EIP-712 "domain" is for

EIP-712 is a signing standard designed for structured data. The "Sign" prompt you see in your wallet essentially asks you to sign "Typed Data".

The core part of this data is called the Domain Separator, which typically contains four key fields:

  • name: the application's name

  • version: the version number

  • chainId: the chain ID (e.g., Ethereum mainnet is 1)

  • verifyingContract: the contract address that will verify the signature

Together, these fields uniquely identify exactly what scenario this signature is intended for. A domain mismatch means the signature may not be meant for the current DApp.

2. Why a domain mismatch is a serious warning sign

If the chainId or verifyingContract in the domain doesn't match the website you're connected to, it usually means the signature request is coming from a malicious page.

① Missing chainId: the signature can be replayed on other chains

OWASP's smart contract security standards explicitly state that if an EIP-712 domain lacks chainId and verifyingContract, the signature may be replayed across contracts and chains, allowing an attacker to use your signature from one chain to authorize actions on another.

② Missing verifyingContract: the signature can be used at other contract addresses

Real audit cases on GitHub show: because verifyingContract is missing, the same signature works across multiple contract addresses. An attacker can directly use a signature you gave in one place to call functions elsewhere. In another case, a missing version field caused two different contract versions to have identical domain structures, making signatures reusable between versions.

chainId hardcoded to a fixed value: after a chain fork, signatures may become invalid or replayable

If the chainId in the domain is hardcoded rather than dynamically reading block.chainid, all existing signatures may become invalid after a chain upgrade or fork. If an attacker rebuilds the environment on a forked chain, replay attacks may also occur.

OKX Exchange
A leading global cryptocurrency platform,suitable for both beginners and experienced traders.
New user benefit: 20% off trading fees upon registration!!

3. What to do when you receive a signature request with a domain mismatch

Step 1: Refuse to sign—do not click "Confirm"

  • What to do: Close the signing popup directly. Do not try to modify or confirm it.

  • How to do it:

    • If the wallet popup shows "Sign typed data" with a string that looks like a domain structure, first check whether verifyingContract is the current DApp's contract address.

    • If it shows 0x000... or an address you have never interacted with, reject it.

    • Some wallets (e.g., Phantom, Rabby) highlight domain information directly. Pay special attention to whether chainId and verifyingContract match your current environment.

Step 2: Decode the EIP-712 request with a tool and review the full domain

  • What to do: Before signing, parse the full content of the signature request with a tool.

  • How to do it:

    • Use a browser extension like ShieldForge, which can automatically decode EIP-712 typed data before you sign, showing domain, message, and primaryType, and warning about "infinite approval" values.

    • You can also use the verifyTypedData function from viem to verify offline whether the domain and message match.

  • When is this step complete?: You have confirmed whether every domain field (name, version, chainId, verifyingContract) in the request points to the DApp you are currently interacting with.

Step 3: Only consider signing when the domain matches the current DApp exactly

  • What to do: Confirm that all three of the following conditions are met before you consider signing:

    1. name and version match the current DApp's name and version

    2. chainId matches the chain you are connected to exactly (e.g., mainnet is 1, testnet is 11155111)

    3. verifyingContract is a contract address you can verify on the current page (check on a block explorer)

  • When is this step complete?: Every field has been compared one by one and confirmed correct, with no "close enough" ambiguity.

Prerequisite: Your wallet is connected to a DApp that is requesting you to sign an EIP-712 signature.

Common reason for failure: Users see the words "Sign typed data" and assume it's just a "login", confirming without checking the domain. A huge number of recent asset thefts trace back to blind signing—clicking confirm without knowing what the signature actually contains.

Risk reminder: Hardware wallets or cold wallets offer no extra protection against EIP-712 signatures—because these signatures are designed for offline authorization by nature; they don't need gas or on-chain confirmation. Once you sign, an attacker can immediately use that signature on another chain or at another contract without requiring any further confirmation from you.

After completing these checks, how do you know you're safe?

When you receive an EIP-712 signature request, expand the "Domain" details in your wallet. Confirm that chainId matches the chain ID you are currently connected to, and that verifyingContract is the contract address you are interacting with. If either one doesn't match what you expect, click "Reject". Only proceed if everything matches completely. If you're unsure about a request, decode it with a tool like ShieldForge before deciding.