-
Notifications
You must be signed in to change notification settings - Fork 9
use _validateCancel instead of overriding cancel
#10
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
Changes from 8 commits
f751ec6
d6f0032
5ffeab0
9d378ac
13f18c5
409e406
85c8c15
7a7674b
ce162a6
f83d972
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,38 +14,31 @@ abstract contract GovernorProposalGuardian is Governor { | |||||||||||||||||||||||
| event ProposalGuardianSet(address oldProposalGuardian, address newProposalGuardian); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * @dev Override {IGovernor-cancel} that implements the extended cancellation logic. | ||||||||||||||||||||||||
| * @dev Override `_validateCancel` that implements the extended cancellation logic. | ||||||||||||||||||||||||
| * | ||||||||||||||||||||||||
| * * The {proposalGuardian} can cancel any proposal at any point in the lifecycle. | ||||||||||||||||||||||||
| * * if no proposal guardian is set, the {proposalProposer} can cancel their proposals at any point in the lifecycle. | ||||||||||||||||||||||||
| * * if the proposal guardian is set, the {proposalProposer} keeps their default rights defined in {IGovernor-cancel} (calling `super`). | ||||||||||||||||||||||||
| * * if the proposal guardian is set, the {proposalProposer} keeps their default rights defined in {IGovernor-_validateCancel} (calling `super`). | ||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||
| function cancel( | ||||||||||||||||||||||||
| address[] memory targets, | ||||||||||||||||||||||||
| uint256[] memory values, | ||||||||||||||||||||||||
| bytes[] memory calldatas, | ||||||||||||||||||||||||
| bytes32 descriptionHash | ||||||||||||||||||||||||
| ) public virtual override returns (uint256) { | ||||||||||||||||||||||||
| address caller = _msgSender(); | ||||||||||||||||||||||||
| function _validateCancel(uint256 proposalId, address caller) internal view virtual override returns (bool) { | ||||||||||||||||||||||||
| address guardian = proposalGuardian(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (guardian == address(0)) { | ||||||||||||||||||||||||
| // if there is no proposal guardian | ||||||||||||||||||||||||
| // ... only the proposer can cancel | ||||||||||||||||||||||||
| // ... no restriction on when the proposer can cancel | ||||||||||||||||||||||||
| uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); | ||||||||||||||||||||||||
| address proposer = proposalProposer(proposalId); | ||||||||||||||||||||||||
| if (caller != proposer) revert GovernorOnlyProposer(caller); | ||||||||||||||||||||||||
| return _cancel(targets, values, calldatas, descriptionHash); | ||||||||||||||||||||||||
| if (caller == proposer) return true; | ||||||||||||||||||||||||
| } else if (guardian == caller) { | ||||||||||||||||||||||||
| // if there is a proposal guardian, and the caller is the proposal guardian | ||||||||||||||||||||||||
| // ... just cancel | ||||||||||||||||||||||||
| return _cancel(targets, values, calldatas, descriptionHash); | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| // if there is a proposal guardian, and the caller is not the proposal guardian | ||||||||||||||||||||||||
| // ... apply default behavior | ||||||||||||||||||||||||
| return super.cancel(targets, values, calldatas, descriptionHash); | ||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // if there is no guardian and the caller isn't the proposer or | ||||||||||||||||||||||||
| // there is a proposal guardian, and the caller is not the proposal guardian | ||||||||||||||||||||||||
| // ... apply default behavior | ||||||||||||||||||||||||
| return super._validateCancel(proposalId, caller); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| // if there is no guardian and the caller isn't the proposer or | |
| // there is a proposal guardian, and the caller is not the proposal guardian | |
| // ... apply default behavior | |
| return super._validateCancel(proposalId, caller); | |
| } else { | |
| // if there is no guardian and the caller isn't the proposer or | |
| // there is a proposal guardian, and the caller is not the proposal guardian | |
| // ... apply default behavior | |
| return super._validateCancel(proposalId, caller); | |
| } |
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 approach here was to not require having two separate calls to super. If its required for readability we can do it this way.
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 is a consequence of this discussion: https://github.com/Amxx/openzeppelin-contracts/pull/10/files#r1925693063.
(let keep it to one thread)
Uh oh!
There was an error while loading. Please reload this page.
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 the behavior we want is (no fallback)
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.
and if we want to make do things differently, then I would make it explicit:
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 powerful aspect of this method of validation is that additional overrides can be explicitly more permissive. So calling super in all cases that it would be false allows for it to play nice with another possibly more permissive cancelation policy (say anyone can cancel a proposal with very low participation).
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 can understand the logic, but then it has to be documented accordingly.
Currently the documentation says:
But that is forgetting that the super call could add additional "permission".
Note that there is a case to make that in certain conditions, we could want to activelly disable permission. For example there would be a module that has a flag
disableAllCancelIn that case you don't want the super call to say yes when
disableAllCancelsays "no way". Not saying that is what we want here, but it should be discussed.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 updated the docs accordingly. If we are going in the right direction, we should merge this PR and have further conversation on the main PR?