Core Contracts

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

Quorum is calculated at the moment of execution instead of at the start of voting

Vulnerability Details

Governance#execute is used to schedule a successful proposal, and execute it after a certain period

function execute(uint256 proposalId) external override nonReentrant {
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.executed) revert ProposalAlreadyExecuted(proposalId, block.timestamp);
ProposalState currentState = state(proposalId);
// Check if the proposal is in the correct state for execution
if (currentState == ProposalState.Succeeded) {
// Queue the proposal
_queueProposal(proposalId);
} else if (currentState == ProposalState.Queued) {
// Execute the queued proposal
_executeProposal(proposalId);
}

execute -> state:

ProposalVote storage proposalVote = _proposalVotes[proposalId];
uint256 currentQuorum = proposalVote.forVotes + proposalVote.againstVotes;
uint256 requiredQuorum = quorum();
// Check if quorum is met and votes are in favor
if (currentQuorum < requiredQuorum || proposalVote.forVotes <= proposalVote.againstVotes) {
return ProposalState.Defeated;
}

state -> quorum:

function quorum() public view override returns (uint256) {
return (_veToken.getTotalVotingPower() * quorumNumerator) / QUORUM_DENOMINATOR;
}

as we can see, instead of using the total voting power at the start of the proposal, quorum just uses the current voting power, allowing any user to invalidate a successful proposal by creating enough voting power at any time during the voting.

Proof of Concept

  1. A proposal is created

  2. Voting period starts

  3. 5% of the voting power votes for, nobody votes against (assuming quorum is 4% of the total voting power)

  4. Total voting power increases by 21% by the end of voting

  5. Now quorum is below 4% and the proposal is defeated.

Impact

Invalidation of proposals that should pass the quorum requirement, due to new voting power that was created after the start of the voting.

Double-voting with locks that expire after the start and before the end of voting (vote from account1 -> wait until RAAC tokens are unlocked -> transfer RAAC to account2 -> lock from account2 -> vote from account2).

Recommendations

Use voting power at the start of voting for calculating the quorum.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Governance::quorum uses current total voting power instead of proposal creation snapshot, allowing manipulation of threshold requirements to force proposals to pass or fail

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Governance::quorum uses current total voting power instead of proposal creation snapshot, allowing manipulation of threshold requirements to force proposals to pass or fail

Support

FAQs

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