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.
Hi @frangio this is important EIP, thank you for authoring.
Two questions from me:
What is the rationale choosing bytes1 field instead of byte field or uint8 field?
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?
I think bytes1 and byte are synonyms. As for byte vs integer types, I went with byte because it doesnât have integer semantics.
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 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 domainSeparator:
{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.
@frangio@wighawag , inspired by your discussion about event vs function, given the lesson we learn in ERC721Metadata, it would be nice for an event could be used to notify when an update occurs to of EIP-712Domain
In general, it may not be possible to emit an event when the domain changes. For example, if the chain forks with a new chain id the EIP-712 domain immediately changes and there is no opportunity to trigger that event, unless triggered manually after the fact. That said, it could still be useful to have an optional event.
ERC721Metadata is a good interface, a little pity that it didnât define a way to trigger update, hence EIP-4906 is drafted and serve as a complement to it.
In general, it may not be possible to emit an event when the domain changes. For example, if the chain forks with a new chain id the EIP-712 domain immediately changes and there is no opportunity to trigger that event, unless triggered manually after the fact.
Yes, thatâs the case, it wonât emit an event. It will aways need to be executed TX in order to emit the event.
That said, it could still be useful to have an optional event.
Yes, exactly, this is what I mean. An optional event for implementor to have an option to notify callers who care about change of domain.
I did some more research on backwards compatibility and put together a small app to show that it is possible to reconstruct the EIP-712 domain of contracts that donât impement this EIP by guessing the domain.
Cross posting some editorial questions hoping to get @frangio 's clarification I left on github PR
Discussion: can you share the rationale of extensions being format as uint256 instead of bytes32 ?
Extensions are described by their EIP numbers because EIP-712 states: âFuture extensions to this standard can add new fields [âŚ] new fields should be proposed through the EIP process.â
Here EIP-712 didnât specify what format of fields will be, so itâs open to future designer to design, EIP-5267 is one of such future design.
Q1. Could author share your thoughts into why choose the format of extensions an uint256[] vs bytes32[] or generally bytes? This is one of the problem that EIP-5750 is trying to address and thus when EIP-5267 made a design choice thatâs different, Iâd love to learn the rationale and understand it better. When using uint256[] and described in EIP-5267 as it needs to be a EIP number, does it mean only EIP number will be allowed in the extension as a way to provide extending information? Will EIP number be sufficient? Do you anticipate some of these elements could be re-purposed in the future?
Future extensions to this standard can add new fields with new user-agent behaviour constraints. User-agents are free to use the provided information to inform/warn users or refuse signing. Dapp implementers should not add private fields, new fields should be proposed through the EIP process.
This means that applications that want to use new fields should do so by creating an EIP. The resulting EIP number would go in the extensions array.
Please also see the new code under Reference Implementation showing what supporting an extension EIP would look like.
No, there are no constraints on the number of elements. The reference Solidity implementation returns an empty array, and this is expected to be the most common value.
When EIP-712 says ânew fields should be proposed through the EIP process.â this means there will be exceptions. This means, when you choose âEIP numbersâ as the sole possible value of extensions
it rule out all exceptions that (1) compliant EIP-712 implementations may choose to ignore the âshouldâ wording soft spec of EIP-712 and introduce behavior at their sole discretion without proposing an EIP or (2) the EIP process stops functioning like the YellowPaper or (3) EIP-number stops being a number but some chars like softly proposed by @Pandapip1 and a few others in the debate of how EIP numbers shall be assigned and {revoked, reassigned, corrected}.
it also rule out the case when the EIP number is the only granularity. For example, when used with complicated EIP (EIP-4337), it couldnât specify a sub interface or sub behavior in that EIP or other more complicated EIPs. For example, in a cross-chain validation scenario (EIP-5164 may lead to), EIP or implementer may want to specify a chain-pair in some case and EIP-5267 will be too restrictive (see footnote #1).
If this is indeed the intention of EIP-5267, sure this can be a design choice author makes. But I like to flag this as explicit and suggest we spell out rationales leading to these decisions.
Footnote #1: An counter example is that EIP-1271 doesnât have an extension field, therefore we end-up needing EIP like EIP-6066 to specify a new method and all developers need to re-establish a consensus to follow or not follow that new function.
function isValidSignature(uint256 tokenId, bytes32 hash, bytes calldata data)
Follow up the debate of EIP-1271 lacks a tokenId or general extraData field in the EIP-5750
Or maybe what really needs to be considered is the represent the extensibility of EIP-712, which you wrote
Additionally, the type of the EIP712Domain struct needs to be extended with the subdomain field. This is left out of scope of this reference implementation.