From ca2d1cc4857df3ba99f017d386d9f89d397a8543 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 10:49:56 +0100 Subject: [PATCH 1/8] Enforce proposal status when calling Governor.execute depending on `proposalNeedsQueuing` --- .changeset/silver-falcons-lay.md | 5 +++ contracts/governance/Governor.sol | 3 +- contracts/governance/IGovernor.sol | 5 --- .../extensions/GovernorTimelockCompound.sol | 3 -- test/governance/Governor.test.js | 12 +++---- .../extensions/GovernorTimelockAccess.test.js | 34 ++++++++++++++++--- .../GovernorTimelockCompound.test.js | 24 ++++++++----- .../GovernorTimelockControl.test.js | 16 +++++---- .../GovernorVotesQuorumFraction.test.js | 2 +- 9 files changed, 68 insertions(+), 36 deletions(-) create mode 100644 .changeset/silver-falcons-lay.md diff --git a/.changeset/silver-falcons-lay.md b/.changeset/silver-falcons-lay.md new file mode 100644 index 00000000000..5eedcec2f7d --- /dev/null +++ b/.changeset/silver-falcons-lay.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': minor +--- + +`Governor`: Scrict enforcement of the expected proposal state depending on `proposalNeedsQueuing` when calling `execute`. diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index baffd23e24f..6cdf900590f 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -394,10 +394,11 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes32 descriptionHash ) public payable virtual returns (uint256) { uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + bool needsQueueing = proposalNeedsQueuing(proposalId); _validateStateBitmap( proposalId, - _encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued) + _encodeStateBitmap(needsQueueing ? ProposalState.Queued : ProposalState.Succeeded) ); // mark as executed before calls to avoid reentrancy diff --git a/contracts/governance/IGovernor.sol b/contracts/governance/IGovernor.sol index 0988b4e91ca..916dd41802b 100644 --- a/contracts/governance/IGovernor.sol +++ b/contracts/governance/IGovernor.sol @@ -91,11 +91,6 @@ interface IGovernor is IERC165, IERC6372 { */ error GovernorQueueNotImplemented(); - /** - * @dev The proposal hasn't been queued yet. - */ - error GovernorNotQueuedProposal(uint256 proposalId); - /** * @dev The proposal has already been queued. */ diff --git a/contracts/governance/extensions/GovernorTimelockCompound.sol b/contracts/governance/extensions/GovernorTimelockCompound.sol index 8f6183e8b89..c3225f19865 100644 --- a/contracts/governance/extensions/GovernorTimelockCompound.sol +++ b/contracts/governance/extensions/GovernorTimelockCompound.sol @@ -94,9 +94,6 @@ abstract contract GovernorTimelockCompound is Governor { bytes32 /*descriptionHash*/ ) internal virtual override { uint256 etaSeconds = proposalEta(proposalId); - if (etaSeconds == 0) { - revert GovernorNotQueuedProposal(proposalId); - } Address.sendValue(payable(_timelock), msg.value); for (uint256 i = 0; i < targets.length; ++i) { _timelock.executeTransaction(targets[i], values[i], "", calldatas[i], etaSeconds); diff --git a/test/governance/Governor.test.js b/test/governance/Governor.test.js index ebb5a3884d1..961cd149d5c 100644 --- a/test/governance/Governor.test.js +++ b/test/governance/Governor.test.js @@ -404,7 +404,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Active, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); @@ -417,7 +417,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Active, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); @@ -430,7 +430,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Active, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); @@ -481,7 +481,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Executed, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); }); @@ -569,7 +569,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); @@ -587,7 +587,7 @@ describe('Governor', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index 5eea6478abd..8e335736470 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -238,6 +238,32 @@ describe('GovernorTimelockAccess', function () { await this.helper.setProposal([this.restricted.operation], 'descr'); await this.helper.propose(); expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.false; + await this.helper.waitForSnapshot(); + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + await this.helper.waitForDeadline(); + await expect(this.helper.execute()).to.not.be.reverted; + }); + + it('does need to queue proposals with base delay', async function () { + const roleId = 1n; + const executionDelay = 0n; + const baseDelay = 10n; + + // Set execution delay + await this.manager.connect(this.admin).setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId); + await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay); + + // Set base delay + await this.mock.$_setBaseDelaySeconds(baseDelay); + + await this.helper.setProposal([this.restricted.operation], 'descr'); + await this.helper.propose(); + expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true; + await this.helper.waitForSnapshot(); + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + await this.helper.waitForDeadline(); + // Not queueud, so it should revert + await expect(this.helper.execute()).to.be.reverted; }); it('needs to queue proposals with any delay', async function () { @@ -556,7 +582,7 @@ describe('GovernorTimelockAccess', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), // proposal needs queueing ); }); @@ -602,7 +628,7 @@ describe('GovernorTimelockAccess', function () { .withArgs( original.currentProposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), // proposal needs queueing ); }); @@ -628,7 +654,7 @@ describe('GovernorTimelockAccess', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), // not queueing necessary ); }); @@ -649,7 +675,7 @@ describe('GovernorTimelockAccess', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), // not queueing necessary ); }); diff --git a/test/governance/extensions/GovernorTimelockCompound.test.js b/test/governance/extensions/GovernorTimelockCompound.test.js index cd82481d500..e00a42391cb 100644 --- a/test/governance/extensions/GovernorTimelockCompound.test.js +++ b/test/governance/extensions/GovernorTimelockCompound.test.js @@ -156,8 +156,12 @@ describe('GovernorTimelockCompound', function () { .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyQueuedProposal') .withArgs(id); await expect(this.helper.execute()) - .to.be.revertedWithCustomError(this.mock, 'GovernorNotQueuedProposal') - .withArgs(id); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs( + this.proposal.id, + ProposalState.Succeeded, + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), + ); }); }); @@ -168,11 +172,13 @@ describe('GovernorTimelockCompound', function () { await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(1n); - expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Succeeded); - await expect(this.helper.execute()) - .to.be.revertedWithCustomError(this.mock, 'GovernorNotQueuedProposal') - .withArgs(this.proposal.id); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs( + this.proposal.id, + ProposalState.Succeeded, + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), + ); }); it('if too early', async function () { @@ -204,7 +210,7 @@ describe('GovernorTimelockCompound', function () { .withArgs( this.proposal.id, ProposalState.Expired, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); @@ -222,7 +228,7 @@ describe('GovernorTimelockCompound', function () { .withArgs( this.proposal.id, ProposalState.Executed, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); }); @@ -317,7 +323,7 @@ describe('GovernorTimelockCompound', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); }); diff --git a/test/governance/extensions/GovernorTimelockControl.test.js b/test/governance/extensions/GovernorTimelockControl.test.js index 507c7e27832..02e1ff2bc8d 100644 --- a/test/governance/extensions/GovernorTimelockControl.test.js +++ b/test/governance/extensions/GovernorTimelockControl.test.js @@ -166,11 +166,13 @@ describe('GovernorTimelockControl', function () { await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(1n); - expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Succeeded); - await expect(this.helper.execute()) - .to.be.revertedWithCustomError(this.timelock, 'TimelockUnexpectedOperationState') - .withArgs(this.proposal.timelockid, GovernorHelper.proposalStatesToBitMap(OperationState.Ready)); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs( + this.proposal.id, + ProposalState.Succeeded, + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), + ); }); it('if too early', async function () { @@ -201,7 +203,7 @@ describe('GovernorTimelockControl', function () { .withArgs( this.proposal.id, ProposalState.Executed, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); @@ -224,7 +226,7 @@ describe('GovernorTimelockControl', function () { .withArgs( this.proposal.id, ProposalState.Executed, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); }); @@ -270,7 +272,7 @@ describe('GovernorTimelockControl', function () { .withArgs( this.proposal.id, ProposalState.Canceled, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); }); diff --git a/test/governance/extensions/GovernorVotesQuorumFraction.test.js b/test/governance/extensions/GovernorVotesQuorumFraction.test.js index 99afd393173..6dafaa9e3fc 100644 --- a/test/governance/extensions/GovernorVotesQuorumFraction.test.js +++ b/test/governance/extensions/GovernorVotesQuorumFraction.test.js @@ -92,7 +92,7 @@ describe('GovernorVotesQuorumFraction', function () { .withArgs( this.proposal.id, ProposalState.Defeated, - GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]), + GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]), ); }); From 3d1f63948fe874f321407b4cf2f0d7167e9e3be9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 10:55:45 +0100 Subject: [PATCH 2/8] update tests --- .../extensions/GovernorTimelockAccess.test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index 8e335736470..de8eb38b6fb 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -241,6 +241,8 @@ describe('GovernorTimelockAccess', function () { await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); + + // No need for queuing, so it should not revert await expect(this.helper.execute()).to.not.be.reverted; }); @@ -262,8 +264,15 @@ describe('GovernorTimelockAccess', function () { await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); + // Not queueud, so it should revert - await expect(this.helper.execute()).to.be.reverted; + await expect(this.helper.execute()) + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs( + this.helper.currentProposal.id, + ProposalState.Succeeded, + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), + ); }); it('needs to queue proposals with any delay', async function () { From bfcbae80d3a6244b275a2a0af89bd7631ba0b63a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 10:57:25 +0100 Subject: [PATCH 3/8] update tests --- .../extensions/GovernorTimelockAccess.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index de8eb38b6fb..437eab61790 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -238,6 +238,7 @@ describe('GovernorTimelockAccess', function () { await this.helper.setProposal([this.restricted.operation], 'descr'); await this.helper.propose(); expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.false; + await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); @@ -261,6 +262,7 @@ describe('GovernorTimelockAccess', function () { await this.helper.setProposal([this.restricted.operation], 'descr'); await this.helper.propose(); expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true; + await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); @@ -298,6 +300,19 @@ describe('GovernorTimelockAccess', function () { ); await this.helper.propose(); expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true; + + await this.helper.waitForSnapshot(); + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + await this.helper.waitForDeadline(); + + // Not queueud, so it should revert + await expect(this.helper.execute()) + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs( + this.helper.currentProposal.id, + ProposalState.Succeeded, + GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), + ); } }); From 38b346f4ba8de1f782e87a90c555cae8b84f22bc Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 11:10:54 +0100 Subject: [PATCH 4/8] codespell --- test/governance/extensions/GovernorTimelockAccess.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index 437eab61790..d40843d3a45 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -267,7 +267,7 @@ describe('GovernorTimelockAccess', function () { await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); - // Not queueud, so it should revert + // Not queued, so it should revert await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') .withArgs( @@ -305,7 +305,7 @@ describe('GovernorTimelockAccess', function () { await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await this.helper.waitForDeadline(); - // Not queueud, so it should revert + // Not queued, so it should revert await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') .withArgs( From 52149726f0008799053d193743399bbd81476dd8 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 11:12:43 +0100 Subject: [PATCH 5/8] Update .changeset/silver-falcons-lay.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .changeset/silver-falcons-lay.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silver-falcons-lay.md b/.changeset/silver-falcons-lay.md index 5eedcec2f7d..f3296013128 100644 --- a/.changeset/silver-falcons-lay.md +++ b/.changeset/silver-falcons-lay.md @@ -2,4 +2,4 @@ 'openzeppelin-solidity': minor --- -`Governor`: Scrict enforcement of the expected proposal state depending on `proposalNeedsQueuing` when calling `execute`. +`Governor`: Strict enforcement of the expected proposal state depending on `proposalNeedsQueuing` when calling `execute`. From 2c298a8d8d1726d7a2b35e269b4fccd625c4ebd7 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 11:14:00 +0100 Subject: [PATCH 6/8] Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- test/governance/extensions/GovernorTimelockCompound.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/governance/extensions/GovernorTimelockCompound.test.js b/test/governance/extensions/GovernorTimelockCompound.test.js index e00a42391cb..a2b17da425c 100644 --- a/test/governance/extensions/GovernorTimelockCompound.test.js +++ b/test/governance/extensions/GovernorTimelockCompound.test.js @@ -158,7 +158,7 @@ describe('GovernorTimelockCompound', function () { await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') .withArgs( - this.proposal.id, + id, ProposalState.Succeeded, GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), ); From bb7ea4d26757188f1002f2bb2c39484008e421e9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 11:39:30 +0100 Subject: [PATCH 7/8] lint --- test/governance/extensions/GovernorTimelockCompound.test.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/governance/extensions/GovernorTimelockCompound.test.js b/test/governance/extensions/GovernorTimelockCompound.test.js index a2b17da425c..fc8e1e561b2 100644 --- a/test/governance/extensions/GovernorTimelockCompound.test.js +++ b/test/governance/extensions/GovernorTimelockCompound.test.js @@ -157,11 +157,7 @@ describe('GovernorTimelockCompound', function () { .withArgs(id); await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - id, - ProposalState.Succeeded, - GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), - ); + .withArgs(id, ProposalState.Succeeded, GovernorHelper.proposalStatesToBitMap([ProposalState.Queued])); }); }); From 73ee8d5eaaee473e30af963563561a022e64e23d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 3 Mar 2026 18:48:44 +0100 Subject: [PATCH 8/8] up --- .../extensions/GovernorTimelockAccess.test.js | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index d40843d3a45..3772a4aa956 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -235,9 +235,9 @@ describe('GovernorTimelockAccess', function () { // Set base delay await this.mock.$_setBaseDelaySeconds(baseDelay); - await this.helper.setProposal([this.restricted.operation], 'descr'); + const { id } = await this.helper.setProposal([this.restricted.operation], 'descr'); await this.helper.propose(); - expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.false; + expect(await this.mock.proposalNeedsQueuing(id)).to.be.false; await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); @@ -259,9 +259,9 @@ describe('GovernorTimelockAccess', function () { // Set base delay await this.mock.$_setBaseDelaySeconds(baseDelay); - await this.helper.setProposal([this.restricted.operation], 'descr'); + const { id } = await this.helper.setProposal([this.restricted.operation], 'descr'); await this.helper.propose(); - expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true; + expect(await this.mock.proposalNeedsQueuing(id)).to.be.true; await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); @@ -270,11 +270,7 @@ describe('GovernorTimelockAccess', function () { // Not queued, so it should revert await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.helper.currentProposal.id, - ProposalState.Succeeded, - GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), - ); + .withArgs(id, ProposalState.Succeeded, GovernorHelper.proposalStatesToBitMap([ProposalState.Queued])); }); it('needs to queue proposals with any delay', async function () { @@ -294,12 +290,12 @@ describe('GovernorTimelockAccess', function () { // Set base delay await this.mock.$_setBaseDelaySeconds(baseDelay); - await this.helper.setProposal( + const { id } = await this.helper.setProposal( [this.restricted.operation], `executionDelay=${executionDelay.toString()}}baseDelay=${baseDelay.toString()}}`, ); await this.helper.propose(); - expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true; + expect(await this.mock.proposalNeedsQueuing(id)).to.be.true; await this.helper.waitForSnapshot(); await this.helper.connect(this.voter1).vote({ support: VoteType.For }); @@ -308,11 +304,7 @@ describe('GovernorTimelockAccess', function () { // Not queued, so it should revert await expect(this.helper.execute()) .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.helper.currentProposal.id, - ProposalState.Succeeded, - GovernorHelper.proposalStatesToBitMap([ProposalState.Queued]), - ); + .withArgs(id, ProposalState.Succeeded, GovernorHelper.proposalStatesToBitMap([ProposalState.Queued])); } });