Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

Passed proposals can be canceled by anyone if proposer's voting power drops below threshold

Summary

The Governance::cancel() function allows anyone to cancel a passed proposal if the proposer's voting power drops below the proposal threshold, which can happen naturally due to vote decay.

Vulnerability Details

The cancel() function in Governance.sol allows cancellation of proposals in any state except Executed, contradicting the NatSpec which states it should only cancel active proposals. Moreover, if we look at the parameters of the error, the state of the proposal for which the cancelation should be allowed is Active.

The error's definition:

error InvalidProposalState(
uint256 proposalId,
ProposalState current,
ProposalState required,
string reason
);

The key problematic code:

function cancel(uint256 proposalId) external override {
// Only checks if proposal is executed
@> if (currentState == ProposalState.Executed) {
@> revert InvalidProposalState(proposalId, currentState, ProposalState.Active, "Cannot cancel executed proposal");
}
...
}

Proof of Concept

  1. Alice creates a proposal with sufficient voting power (>= proposalThreshold)

  2. The proposal passes voting and enters Succeeded state

  3. Due to vote decay, Alice's voting power naturally drops below proposalThreshold

  4. Bob (or any user) can now call cancel() on the successful proposal

  5. The proposal is canceled despite having passed voting

Impact

  • Successful proposals can be maliciously canceled before execution

  • Undermines the governance process since passed proposals are not guaranteed to execute

  • Could be exploited to prevent unfavorable but legitimate proposals from executing

Recommendations

  1. Only allow cancellation during active voting:

function cancel(uint256 proposalId) external override {
ProposalState currentState = state(proposalId);
- if (currentState == ProposalState.Executed) {
+ if (currentState != ProposalState.Active) {
revert InvalidProposalState(proposalId, currentState, ProposalState.Active, "Can only cancel active proposals");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Governance::cancel allows canceling proposals in Succeeded and Queued states, enabling single actors to override community decisions

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Governance::cancel allows canceling proposals in Succeeded and Queued states, enabling single actors to override community decisions

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.