EIP-5267: Retrieval of EIP-712 domain

Currently, in order to instantiate a web3 Contract object, libraries like Ethers require the user to submit a minimum of the contract address and the contract ABI (in either human-readable string form or JSON). The ABI is output by Solidity. It would be very annoying if the user had to go in and manually edit the ABI file to manually change these parameter names every time a new version of the contract is built and deployed, from the versions that were built (e.g. _name and _version) to the versions that the user wants to use in the JS API (e.g. name and version).

The creator of Ethers is considering pulling the ABI directly from Etherscan, so that to instantiate a Contract object, you would only have to specify the address of an Etherscan-verified contract. At that point, whatever is built by Solidity, and deployed, is what will be automatically exposed in Javascript.

So yes, names exposed in Solidity do in fact matter in Javascript code.

An application or a library that instantiates a Contract object in order to consume its EIP-5267 interface would do so based on a user-provided address and a known ABI embedded in the application or library. The known ABI would have known names, they would not depend on the names that were present in the contract source code.

Take an ERC20 wallet as an example. When the user loads a new token address, the wallet will not fetch the ABI from an explorer, it will interact with it through a known ABI for ERC20 tokens. The same thing should happen in an application or library that interacts with EIP-5267 compliant contracts.

@frangio’s ERC lightning talk at Devcon in Bogota on EIP-5267 ERC Lighting Talks - YouTube

Hi @frangio this is important EIP, thank you for authoring.

Two questions from me:

  1. What is the rationale choosing bytes1 field instead of byte field or uint8 field?
  2. What is the rationale of putting a salt field in the domain? It seems not reasonable to get salt from remote, unless the understanding of salt is different, could you ellaborate?
  1. I think bytes1 and byte are synonyms. As for byte vs integer types, I went with byte because it doesn’t have integer semantics.
  2. The inclusion of salt in the domain is taken directly out of EIP-712. I think it should be seen as a salt to the domain separator, and shouldn’t be confused with a salt for the message being signed, which would be different.

I could not imagine how salt could be retrieved from the function state, are you referring to nonce instead?

In the current snapshot of reference implementation, you gave

pragma solidity 0.8.0;

contract EIP712VerifyingContract {
  function eip712Domain() external view returns (
      bytes1 fields,
      string memory name,
      string memory version,
      uint256 chainId,
      address verifyingContract,
      bytes32 salt,
      uint256[] memory extensions
  ) {
      return (
          hex"0d", // 01101
          new uint256[](0)

which shows salt as 0.

Can you give more real example of how salt will be generated from contract function?

This EIP makes no statements about the semantics of salt. All that EIP-712 says is:

a disambiguating salt for the protocol. This can be used as a domain separator of last resort.

I see. Maybe just the name salt is confusing, but I can understand the 712’s using it as a last resort to prevent replay attack if chainId is not sufficient to disambiguate…

QQ: Clarify computation of domainSeparator, or provide an interface for implementors to decide

domainSeparator = hashStruct(eip712Domain)

to make it more convenient for client to directly use.

This is because with the field uint256[] memory extensions, I assume there is two ways. to interpret the potential computation of

  • {fields, name, version, chainId, contractAddress,salt} // Original EIP-712
  • {fields, name, version, chainId, contractAddress,salt, extensions} // EIP-712 plus extensions introduced in EIP-5267

If extensions are present they must be included in the domain (but the field would not be an extensions field, it would be other fields defined by the extensions). If this is not clear I can add an example.