foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.12k stars 1.68k forks source link

Cheatcode: EIP712 canonical hashing #4818

Open marktoda opened 1 year ago

marktoda commented 1 year ago

Component

Forge

Describe the feature you would like

Motivation

One of the hardest things to properly test in Foundry is EIP-712 encoding and hashing. Efficiently encoding EIP-712 in Solidity generally requires manual declaration of string types and abi encoding of values. In testing, there is no way to double-check that this encoding is actually consistent with the EIP-712 spec. Some catches and edge cases of EIP-712 spec are especially easy to accidentally mess up, i.e. alphabetic ordering of sub-types. This is especially important as signed messages become more widely used, i.e. for EIP-4337.

Currently the best approach for this afaik is to write typescript tests using ethers' TypedDataEncoder to verify

Feature

A cheatcode that creates canonical encodings / typehashes for EIP-712 objects. Ideal API:

vm.hashType(MyStruct) => bytes32 typeHash
vm.hashStruct(MyStruct struct) => bytes32 hash

I'm not sure how easy the introspection will be, but this would be an invaluable feature to cover one of the last un-testable cases in Foundry

Additional context

No response

marktoda commented 1 year ago

Example encoding library https://github.com/Uniswap/permit2/blob/main/src/libraries/PermitHash.sol - you could switch around the string typings and tests would still pass. Instead we rely on separate tests from our typescript SDK https://github.com/Uniswap/permit2-sdk/blob/cb84da1accf9f475d11e96fff7e5b255d55dcc14/src/allowanceTransfer.ts#L103 to ensure the solidity-generated hashes match canonical hashes

prestwich commented 1 year ago

vm.hashType(MyStruct) => bytes32 typeHash

This cannot compile in Solidity, as there is no polymorphism. Therefore we can't make a function that accepts any struct trpe

It's hard for me to see a good way to inject type-level information into foundry 🤔

marktoda commented 1 year ago

yeah i was thinking it would need some kind of introspection.. maybe like vm.hashType("MyStruct") and the cheatcode like looks up the struct def in the abi? its a bit wonky though for sure

prestwich commented 1 year ago

yeah i was thinking it would need some kind of introspection.. maybe like vm.hashType("MyStruct") and the cheatcode like looks up the struct def in the abi? its a bit wonky though for sure

yeah, that could work 🤔