-
Notifications
You must be signed in to change notification settings - Fork 81
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
Sign Full User Operation Data #177
Conversation
Pull Request Test Coverage Report for Build 7044495496
💛 - Coveralls |
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.
The solidity implementations looks good.
I could not find test that check that initCode and paymasterData can not be changed.
The TS library changed to additionally sign |
@rmeissner - added a new unit test in 467df98 that verifies that if any |
This PR adjusts the Safe module to sign all of the
UserOperation
struct data instead of the reduced set of fields it was originally signing. Namely, this means that theSafeOp
EIP-712 struct needs to also include the fields:initCode
: ensures that initialisation works exactly as the user specifiedpaymasterAndData
: ensures that user operations are tied to specific paymaster callsUnfortunately, this required some non-trivial changes to the module code in order to accommodate all of these fields. Namely:
SafeOp
field order was changed to match that of theUserOperation
. This was done for two reasons:UserOperation
fields are accounted forSafeOp
for computing the signing message when copying from aUserOperation calldata
. While we don’t make use of this in the code, I believe it is a nice property to have.getOperationHash
now takes aUserOperation calldata
instead of all user operation fields (because of the Solidity “stack too deep” limitation).b3e1785 contains other versions of possible implementations for computing the signing message for the Safe operation, namely:
calldatacopy
to setup theSafeOp
struct in memory for hashing, this is the most efficient by around 310 gas compared to the current implementation, but has a lot of magic and is not easy to understand, hence it was not used. (code)uint256[14] memory
, while this requires slightly less boiler plate, it is not as easy to understand (IMO) and was less gas-efficient. (code)abi.encode
as usual, but using some careful tricks to avoid “stack too deep” errors. Ironically, this was the least gas efficient of all the methods, and when building with instrumentation for generating a coverage report, would run into “stack too deep” errors anyway. (code)