-
Notifications
You must be signed in to change notification settings - Fork 196
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
feat(world): add callFrom entry point #1364
Conversation
🦋 Changeset detectedLatest commit: 042893f The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@@ -10,4 +10,5 @@ interface IWorldErrors { | |||
error FunctionSelectorExists(bytes4 functionSelector); | |||
error FunctionSelectorNotFound(bytes4 functionSelector); | |||
error ModuleAlreadyInstalled(string module); | |||
error NoDelegationFound(address grantor, address grantee); |
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.
error NoDelegationFound(address grantor, address grantee); | |
error DelegationNotFound(address grantor, address grantee); |
(for consistency with our other errors)
Did some refactors around |
31a033a
to
3c13457
Compare
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
3c13457
to
79125bc
Compare
79125bc
to
70e8c7d
Compare
*/ | ||
function registerDelegation( | ||
address delegatee, | ||
bytes32 delegationControl, |
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.
took me a bit to realize we switched from address to resource selector/ID, and wondering if we should clarify the naming here to delegationControlId
or something?
resourceSelector: resourceSelector, | ||
funcSelectorAndArgsHash: funcSelectorAndArgsHash, | ||
availableCalls: availableCalls - 1 | ||
}); |
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.
should we delete once we get to zero?
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 can be unchecked, since you do availableCalls > 0
already
import { DelegationControl } from "../../DelegationControl.sol"; | ||
import { DisposableDelegations } from "./tables/DisposableDelegations.sol"; | ||
|
||
contract DisposableDelegationControl is DelegationControl { |
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 like this better than "decaying" 👍
Another potential name idea is "callbound" (to go with "timebound")
|
||
// Set the timestamp to maxTimestamp+1 and expect the delegation to be expired | ||
vm.warp(maxTimestamp + 1); | ||
vm.expectRevert(abi.encodeWithSelector(IWorldErrors.DelegationNotFound.selector, delegator, delegatee)); |
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.
tiny thing but I tend to put the expectRevert
immediately before the thing we expect to revert, to not confuse this with "I expect vm.prank
to revert"
@@ -0,0 +1,55 @@ | |||
// SPDX-License-Identifier: MIT |
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.
thoughts on just delegations
instead of std-delegations
for the dir name?
oh nevermind, this seems to reflect the module name and these files are tied to the module
resourceSelector: resourceSelector, | ||
funcSelectorAndArgsHash: funcSelectorAndArgsHash, | ||
availableCalls: availableCalls - 1 | ||
}); |
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 can be unchecked, since you do availableCalls > 0
already
bytes16 constant MODULE_NAME = bytes16("stddelegations.m"); | ||
|
||
// Disposable delegation | ||
bytes32 constant DISPOSABLE_DELEGATION = bytes32(abi.encodePacked(ROOT_NAMESPACE, bytes16("disposable.d"))); | ||
|
||
// Timebound delegation | ||
bytes32 constant TIMEBOUND_DELEGATION = bytes32(abi.encodePacked(ROOT_NAMESPACE, bytes16("timebound.d"))); |
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.
should it perhaps have a MODULE_NAMESPACE
?
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.
My thinking was that this module should ideally be installed as a root module (so it can install the systems as root systems), because it reduces the gas cost of all systems that read or change state (around 8k for the calls to DisposableDelegationSystem
)
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 think I have my head wrapped around the end-to-end, but are these delegation/callfrom checks always routed through the world? Ultimately wondering if it would be useful to inherit the namespace or allow the namespace to be configured, or if that only has negative consequences (only used by world, only more gas)
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.
Yes, they are always routed through the World. The main challenge is that the delegation check system needs to know which table to access. We could make this dynamic and store the namespace in which the module is registered in storage and then load it from storage in the system, but that would cost more gas. A cheaper alternative would be to just use two different modules for root and non-root installations (it only needs to be installed once per world, so the namespace for non-root could also be fixed). For now, I'd just go with providing the root version, because I'd expect this standard module to be installed by default - if we find there's a need for a non-root version (to be installed on worlds that don't have the root version installed by default), we can just add another version of the module later
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.
root only for now as the default/expected/most common path is totally fine by me
|
||
if (availableCalls > 0) { | ||
// Decrement the number of available calls | ||
unchecked { |
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 know the consequences of unchecked
but is it safe for us to wrap this whole statement vs just the decrement? Would unchecked
apply to the .set()
or _msgSender()
calls?
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 think it would
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.
moved it outside of the block, gas didn't change so seems like unchecked doesn't impact the nested calls, but fells still cleaner to have it explicit
fixes #1358
see changeset for details on this change