-
Notifications
You must be signed in to change notification settings - Fork 67
feat: add native timelock to account keys #329 #332
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?
feat: add native timelock to account keys #329 #332
Conversation
… and decoding on storage and loading accordingly
…ons help queuing and executing for (ithacaxyz#329)
…uteTimeline which will used to recalculate digest to verify and then execute (ithacaxyz#329)
7b94a60 to
c966be3
Compare
…ck field, payment spend separation, relayer concepts, and timelocker payment implementation. These files are no longer needed as the project evolves.
legion2002
left a comment
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.
I think this PR is on the right track. Requested a few implementation detail changes.
Also can you please rebase with latest main to remove old dependencies like devtools and safe-singleton deployer, and also update to latest foundry nightly linting.
src/IthacaAccount.sol
Outdated
| keyHash: keyHash, | ||
| readyTimestamp: uint40(block.timestamp + getKey(keyHash).timelock) | ||
| }); | ||
| bytes32 timelockHash = _addTimelock(timelocker, computeDigest(calls, nonce)); |
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.
This approach has an intricacy that the relayer payment and the spending limit check happens at the time of adding the timelock.
Not at the time of actually executing it.
I think this could lead to some weird kinds of attacks and inconsistencies. Like the relayer takes the payments, but never executes the action after the timelock.
Or the spending limit changes by the time the timelock is executed, so you can bypass spending limits.
A cleaner way to do this would be, to add a separate prepTimelock function. Where you can pass in just the calls and nonce ( or maybe user can directly pass in the digest ), and it adds the digest to the timelock mapping.
Then this execute checks that for timelocked keys, the timelock should already have passed. If not it reverts.
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 spend limit checks happens at the time of executing. As the function executeTimelock calls the GuardedExecutor._execute(Call[] calldata calls, bytes32 keyHash) in line 658.
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.
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.
I don't like the idea of adding another execution input with executeTimelock since it is not 7821 compliant.
We should keep the same execute() function, but instead create a new function like startTimelock which adds the timelock key to the storage, and then someone can call the normal execute function later to do the actual execution.
In this case we would just check the timelock status in the main execute function
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.
Hey @legion2002, updated the execution flow. Now, the new prepTimelock function is used to add a timelocked and validateTimelockIsExecutable helps unwrapAndValidateSignature validate the timelock, and execution goes through execute.
The new optimisations will be with:
- Handle storage bloat from timelocks, as
executeis used to execute the timelock, we are not removing the timelock from storage. Either add a manual cleaning process or somehow trigger a cleanup by detecting in theexecutefunction itself. - Add a way to cancel a pending timelock. We could do it by invalidating the nonce.
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.
Good work with this! Having the validateTimelock function in unwrapAndValidateSignature makes sense, specially because you don't want a key to transfer the money out of your account using some kind of permit magic.
Having said that, we only allow super admin keys to do isValidSignature so maybe it is a better idea to validate timelock just during execution, and allow the key to make any unwrapAndValidateSignature signatures, without timelock.
I am leaning towards the latter, because this means we can reduce storage bloat, by checking timelock inside the execution and then removing it.
Also for cancelling a pending timelock, we can just allow the key itself, or any admin key to cancel any timelock.
ButI think the PR is at a good place right for now.
We'll figure out what's the right time to get this in, depending on how we'll schedule the next few releases.
Thanks for your contribution! Will let you know when/if we plan to schedule the next release.
…ssociated checks. Simply clear the storage.
…imelockHashes' to 'timelockDigests' and updating associated event parameters.
…ks instead of `_execute` and now `_execute` exeuctes timelocked upon passing.
…amp` with `startTimestamp`. Enhance `prepTimelock` , `_execute`, `unwrapAndValidateSignature` and add a`validateTimelockIsExecutable` functions for improved execution flow.
No description provided.