-
Notifications
You must be signed in to change notification settings - Fork 4
Implement 7739 #140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement 7739 #140
Conversation
/// @notice An abstract contract that implements the ERC-7739 standard | ||
/// @notice This contract assumes that all data verified through ERC-1271 `isValidSignature` implements the defensive nested hashing scheme defined in EIP-7739 | ||
/// @dev See https://eips.ethereum.org/EIPS/eip-7739 | ||
abstract contract ERC7739 is EIP712 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level comment.. but why is this a contract? It seems like it might just be better as a re-useable library? All of the functions defined here are private and I feel like we could re-architect it in a way where we wouldnt have to inherit from 712 and rather pass in any domain separator info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I moved some funcs to the library so this base contract is mostly just _isValidTypedDataSig
and _isValidNestedPersonalSignature
. I think it might be a bit tricky to not inherit from 712 because we need to use the 712 domain in two different ways (domain separator for personal sign) and domainBytes for nested 712
// signature is first 65 bytes of wrappedSignature + 0x | ||
const signatureLength = 130 // 65 * 2 | ||
const start = 2; // skip the first 0x | ||
const signature = '0x' + wrappedSignature.slice(start, start + signatureLength); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flagging this FYI:
- Viem returns a wrapped signature so we have to slice off the first 0x and 65 bytes for the actual signature to compare against
key.verify
in ffi test
src/MinimalDelegation.sol
Outdated
|
||
Key memory key = getKey(keyHash); | ||
bool isValid = key.verify(digest, signature); | ||
|
||
// Must be branched because we do abi decoding in memory which will throw since the ecnoding schemes are different |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flag here also that decoding in memory makes the implementation a little awkaward. Comment here says more
/// @notice We don't care how the hash was computed for personal sign, and it does not match the typestring above | ||
/// i.e. keccak256("\x19Ethereum Signed Message:\n" || len(someMessage) || someMessage) | ||
function hash(bytes32 message) internal pure returns (bytes32) { | ||
return keccak256(abi.encode(PERSONAL_SIGN_TYPEHASH, message)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm this seems wrong? the personal sign type defines the input as a bytes param and here it is already a bytes32?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I asked viem to see what the reasoning is
Implement ERC7739 per the spec: https://eips.ethereum.org/EIPS/eip-7739 , which defines dynamic nested 712 encoding.
Files:
Inspired by https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/master/contracts/utils/cryptography/ERC7739.sol
Base contract implementing logic for verifying nested typed data sign signatures and personal signatures. Handles decoding of wrapped signatures and generating the correct hashTypedDataV4 based on the current account's domainSeparator.
Modified from https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/master/contracts/utils/cryptography/ERC7739Utils.sol
Util contract implementing
decodeContentsDescr
which iterates over a string in memory to find thecontentsName
, handling bothimplicit
andexplicit
modes. For more info, see https://eips.ethereum.org/EIPS/eip-7739#contentsdescription-with-implicit-and-explicit-modes. The main change I made here was to do string operations in memory instead of calldata. I'm open to calldata just wanted to do it in memory to get it working 😂712 hashing logic for typed data sign, generates dynamic type hash and name.
Applies simple 712 hash over a hashed eth personal sign digest.