Core Contracts

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

Incorrect Proposal Cancellation Logic in Governance Contract

Summary

The cancel function in the Governance.sol contract contains flawed logic that restricts proposal cancellation in unintended ways. While the intended design allows cancellation by the proposer or when the proposer's voting power falls below the proposalThreshold, the current implementation incorrectly prevents cancellation unless the proposer initiates it or their voting power remains sufficient.

Vulnerability Details

The cancel function is designed to allow a proposal to be canceled in two scenarios:

  1. The caller (msg.sender) is the proposer of the proposal.

  2. The proposer's voting power drops below the proposalThreshold, enabling anyone to cancel it.

  • However, the current condition of the code is:

    if (msg.sender != proposal.proposer &&
    _veToken.getVotingPower(proposal.proposer) >= proposalThreshold) { // ❌ REVERSED CONDITION
    revert InsufficientProposerVotes(proposal.proposer,
    _veToken.getVotingPower(proposal.proposer), proposalThreshold, "Proposer lost required voting power");
    }

This logic incorrectly reverts if the proposer's voting power is still sufficient (>= proposalThreshold), meaning cancellation is only possible when:

  1. The caller is the proposer, or

  2. The proposer's voting power is still above the threshold (contrary to the intended design).

As a result, no one can cancel a proposal when the proposer's voting power drops below the threshold unless they are the proposer, which contradicts the governance protection mechanism.

Impact

  • Reduced governance reliability and transparency.

  • Potential for proposal manipulation or stalled governance processes.

Tools Used

Manual Review

Recommendations

Update the condition in the cancel function to correctly allow cancellation when the proposer's voting power falls below proposalThreshold. Replace the current flawed check with:

function cancel(uint256 proposalId) external override {
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.startTime == 0) revert ProposalDoesNotExist(proposalId);
ProposalState currentState = state(proposalId);
if (currentState == ProposalState.Executed) {
revert InvalidProposalState(proposalId, currentState, ProposalState.Active, "Cannot cancel executed proposal");
}
uint256 proposerVotingPower = _veToken.getVotingPower(proposal.proposer);
if (msg.sender != proposal.proposer && proposerVotingPower >= proposalThreshold) {
revert("Only proposer or below threshold can cancel");
}
proposal.canceled = true;
emit ProposalCanceled(proposalId, msg.sender, "Proposal canceled");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!