Skip to content

Commit

Permalink
chore: allow proposer to cancel while pending, active, succeeded, and…
Browse files Browse the repository at this point in the history
… queued
  • Loading branch information
arr00 committed Oct 25, 2024
1 parent bcdfa84 commit 8f822f1
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 26 deletions.
9 changes: 6 additions & 3 deletions contracts/governance/Governor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,12 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
// changes it. The `hashProposal` duplication has a cost that is limited, and that we accept.
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);

// public cancel restrictions (on top of existing _cancel restrictions).
_validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Pending));
if (_msgSender() != proposalProposer(proposalId)) {
address proposer = proposalProposer(proposalId);
if (proposer == address(0)) {
revert GovernorNonexistentProposal(proposalId);
}

if (_msgSender() != proposer) {
revert GovernorOnlyProposer(_msgSender());
}

Expand Down
34 changes: 11 additions & 23 deletions test/governance/Governor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -632,27 +632,17 @@ describe('Governor', function () {
await this.helper.propose();
await this.helper.waitForSnapshot(1n); // snapshot + 1 block

await expect(this.helper.cancel('external'))
.to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
.withArgs(
this.proposal.id,
ProposalState.Active,
GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
);
await this.helper.cancel('external');
expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
});

it('after vote', async function () {
await this.helper.propose();
await this.helper.waitForSnapshot();
await this.helper.connect(this.voter1).vote({ support: VoteType.For });

await expect(this.helper.cancel('external'))
.to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
.withArgs(
this.proposal.id,
ProposalState.Active,
GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
);
await this.helper.connect(this.owner).cancel('external');
expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
});

it('after deadline', async function () {
Expand All @@ -661,13 +651,8 @@ describe('Governor', function () {
await this.helper.connect(this.voter1).vote({ support: VoteType.For });
await this.helper.waitForDeadline();

await expect(this.helper.cancel('external'))
.to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
.withArgs(
this.proposal.id,
ProposalState.Succeeded,
GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
);
await this.helper.connect(this.owner).cancel('external');
expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
});

it('after execution', async function () {
Expand All @@ -677,12 +662,15 @@ describe('Governor', function () {
await this.helper.waitForDeadline();
await this.helper.execute();

await expect(this.helper.cancel('external'))
await expect(this.helper.connect(this.owner).cancel('external'))
.to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
.withArgs(
this.proposal.id,
ProposalState.Executed,
GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
GovernorHelper.proposalStatesToBitMap(
[ProposalState.Canceled, ProposalState.Expired, ProposalState.Executed],
{ inverted: true },
),
);
});
});
Expand Down

0 comments on commit 8f822f1

Please sign in to comment.