Core Contracts

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

Canceled proposals can still receive votes due to missing state check

Summary

The castVote() function lacks validation of proposal state, allowing users to vote on canceled proposals which pollutes vote tracking data.

Vulnerability Details

In Governance::castVote(), there is no check to verify if the proposal has been canceled before accepting votes. The function only validates:

  1. Proposal exists

  2. Vote timing (after start, before end)

  3. User hasn't voted before

  4. User has voting power

function castVote(uint256 proposalId, bool support) external override returns (uint256) {
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.startTime == 0) revert ProposalDoesNotExist(proposalId);
if (block.timestamp < proposal.startTime) {
revert VotingNotStarted(proposalId, proposal.startTime, block.timestamp);
}
if (block.timestamp > proposal.endTime) {
revert VotingEnded(proposalId, proposal.endTime, block.timestamp);
}
// Missing check for proposal.canceled
...
}

The root cause is the missing validation of proposal.canceled status before processing the vote.

Impact

While this issue has LOW severity since canceled proposals cannot be executed regardless of votes, it allows:

  1. Misleading vote statistics for canceled proposals

  2. Unnecessary state changes and gas costs for users voting on canceled proposals

Recommendations

Approach 1: Add State Check

function castVote(uint256 proposalId, bool support) external override returns (uint256) {
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.startTime == 0) revert ProposalDoesNotExist(proposalId);
+ if (proposal.canceled) revert ProposalCanceled(proposalId);
...
}

Approach 2: Use State Function

function castVote(uint256 proposalId, bool support) external override returns (uint256) {
ProposalCore storage proposal = _proposals[proposalId];
+ ProposalState currentState = state(proposalId);
+ if (currentState != ProposalState.Active) {
+ revert InvalidProposalState(proposalId, currentState, ProposalState.Active);
+ }
...
}
Updates

Lead Judging Commences

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

Governance::castVote lacks canceled/executed proposal check, allowing users to waste gas voting on proposals that can never be executed

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

Governance::castVote lacks canceled/executed proposal check, allowing users to waste gas voting on proposals that can never be executed

Support

FAQs

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

Give us feedback!