Is the verifyingContract field in the eip712Domain used anywhere practically, e.g. calling to verify the signature, etc. etc.? Or is it just another protection trick for signature replay attacks?

Here's what the docs say, but I want to confirm:

Definition of domainSeparator. domainSeparator = hashStruct(eip712Domain) where the type of eip712Domain is a struct named EIP712Domain with one or more of the below fields. Protocol designers only need to include the fields that make sense for their signing domain. Unused fields are left out of the struct type.

  • string name the user readable name of signing domain, i.e. the name of the DApp or the protocol.
  • string version the current major version of the signing domain. Signatures from different versions are not compatible.
  • uint256 chainId the EIP-155 chain id. The user-agent should refuse signing if it does not match the currently active chain.
  • address verifyingContract the address of the contract that will verify the signature. The user-agent may do contract specific phishing prevention.
  • bytes32 salt an disambiguating salt for the protocol. This can be used as a domain separator of last resort.

P.S. What I mean is whether it's used as per the standard specification (not custom code implementations)

(Reference: https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator)

  • 1
    What do you mean by "practical usage"? It is not "just another protection trick", but a crucial component to protect signers from replay attacks, similar to the chainId, but at the contract level. Additionally the wallets, for example, Rabby, explicitly shows the user which contract they are signing a message for, thereby protecting against phishing attacks.
    – tenbits
    Commented Mar 11 at 21:35
  • Thank you!! You answered my question. What I initially meant to ask in my question is whether there's any extension to the EIP-712 standard that makes calls to the verifyingContract like ERC-1271 does, for instance. That's just what the name of the field (verifyingContract) immediately made me think about. But now taking another look at it, I understand that there's probably supposed to be a check during decoding, whether verifyingContract == address(this). Am I correct?
    – Mila A
    Commented Mar 12 at 9:36
  • 1
    It checks indirectly by using address(this) in DomainSeparator: e.g. the permit implementation by OpenZeppelin: github.com/OpenZeppelin/openzeppelin-contracts/blob/…
    – tenbits
    Commented Mar 12 at 9:45
  • 1
    Aah, got it, thank you for explaining well!
    – Mila A
    Commented Mar 13 at 8:49


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.