3

Assume I'm implementing EIP-712 signatures in solidity.

contract Nice { bytes32 private constant BID_TYPE_HASH = keccak256("Bid(uint256 num1,uint256 num2)"); struct Bid { uint256 num1; uint256 num2; } function verify(Bid memory bid) { bytes32 hashed = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( BID_TYPE_HASH, bid.num1, bid.num2 )) )); } } 

The above works great, but what's the rationale of even using BID_TYPE_HASH ? To ask it in better words, what if EIP suggested to do:

bytes32 hashed = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( bid.num1, bid.num2 )) )); 

What could go wrong now ? Domain Separator already distinguishes dapps, so isn't that enough ? Can you provide an example where this suggested code breaks and defeats the use-case ?

2 Answers 2

2

EIP-712 is about "hashing and signing of typed structured data".

It does provide "an extensible mechanism for domain separation" which is important for security, but the goal of EIP-712 is to make it clearer to users what they are signing.

Wallets and applications can use EIP-712 to improve the UX of signing.

For example, seeing 2 structs of type Person here is clearer than just seeing names and (wallet) addresses:

enter image description here

Without the typeHash, the user would actually just see a bytestring for signing:

enter image description here


Now if you accept types, then you need a way to make each type unique: a user should know are they signing typeA or typeB. Hashing is a way to do this. A collision is when 2 types hash to the same value. To give an example of a collision described by Alternative 2 in https://eips.ethereum.org/EIPS/eip-712#rationale-for-typehash, see https://www.4byte.directory/signatures/?bytes4_signature=0x01ffc9a7

A user should know are they signing pizza_mandate_apology(uint256) or supportsInterface(bytes4) and Alternative 2 doesn't distinguish and so it wasn't chosen as the way to compute typeHash.

8
  • I don't believe that's true. While your statement about UX signing is solid, metamask could easily not include typehash in the hash generation and this way, contract side wouldn't even need typehash too which would make things easier. Here, it says that it's about collisions but that's what I don't get. Collisions for what Commented Feb 17, 2024 at 8:34
  • Added more to the answer and does it help? typeHash only useful for types. You're right that sometimes types might not be needed. Commented Feb 21, 2024 at 5:32
  • hi @eth. sorry for the late message. Note that EIP712 doesn't sign exactly what it's showing you on metamask. you sign the following: Mail(Person from,Person to)... concatinated with other things, but metamask doesn't show you this "Mail(Person from,Person to)" string, right ? even if typehash is not included in EIP-712 sign process, metamask could still show you the same on your image 1. what you're having a hard time to explain is if EIP712 creators didn't include typehash in the algorithm at all, what would go wrong :) One nice example would be great starting from client to solidity. Commented Feb 24, 2024 at 16:48
  • Wallets that support EIP-712 should show the whole struct Mail. EIP-712 has the Twitter usernames of the authors, as well as a discussions-to link` that you can try. Someone who understands more deeply may be able to help more. Feel free to post your own answer here with any learnings. Commented Mar 1, 2024 at 8:54
  • take a look at this image - ibb.co/25ZHtTt (the image includes the code as well so easier for you to understand). In order for this to work, inside contract, I have "BID_TYPE_HASH = keccak256("Bid(uint256 amount,Identity bidder)Identity(uint256 userId,uint256 wallet)");" nowhere in metamask, does it show the same thing as BID_TYPE_HASH :) if it did, i would understand your point, but not now :( Commented Mar 1, 2024 at 11:12
0

While the above answer is correct, it does not explain WHY the typehash is included in the EIP. For instance. Wallets could just ask the developer to pass in the struct that defines the underlying data structure and not actually use the hash in the signature. In this example, users could still sign typed data.

In this example, one could argue that scammers can pass in a faulty data structure that resembles the actual data structure in its RLP encoded form. With the typehash, this is impossible because the typehash is integrated into the signature packet, and as a result must be verified on chain with the typehash.

Personally, I think its overkill and added complexity, but that's the standard we are stuck with

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.