Core Contracts

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

Dynamic Quorum Calculation

Code Analysis

The quorum() function is defined as follows:

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

Issue Explanation

  1. Dynamic Calculation: The quorum is calculated based on the current total voting power retrieved from _veToken.getTotalVotingPower(). This means that any changes to the total voting power after a proposal is created will directly affect the quorum requirement.

  2. Manipulation Potential: If an attacker can influence the total voting power (for example, by unlocking or locking tokens), they can manipulate the quorum requirement. This can lead to scenarios where:

    • A proposal is created when the total voting power is high, establishing a quorum based on that higher value.

    • If the attacker subsequently reduces the total voting power (e.g., by unlocking tokens), the quorum requirement decreases, potentially allowing a proposal to pass with significantly less support than originally intended.

Example Attack Scenario

  • Initial State: Assume the total voting power is 10 million tokens, and the quorum is set at 4%:

    • Quorum = 10,000,000 * 0.04 = 400,000 tokens.

  • Proposal Creation: A proposal is created when the total voting power is 10 million, requiring 400,000 votes to pass.

  • Attack Execution: The attacker unlocks tokens, reducing the total voting power to 5 million:

    • New Quorum = 5,000,000 * 0.04 = 200,000 tokens.

  • Outcome: The proposal can now pass with only 200,000 votes, despite potentially having less actual support than required when the proposal was created.

Conclusion

This vulnerability is critical because it undermines the integrity of the governance process. The quorum requirement should be based on a snapshot of the voting power at the time of proposal creation to prevent manipulation during the voting period.

Recommended Mitigation

To address this vulnerability, the quorum calculation should be modified to use a snapshot of the total voting power at the time the proposal is created. This can be achieved by storing the total voting power in the proposal struct when the proposal is created, and then using that stored value for quorum calculations during the voting period.

Proposed Code Update

Here’s a simplified version of how the proposal struct could be modified to include a snapshot of the total voting power:

struct Proposal {
uint256 id;
uint256 totalVotingPowerAtCreation; // New field to store voting power at creation
// ... other fields ...
}
// In the proposal creation function
function createProposal(...) external {
uint256 totalVotingPower = _veToken.getTotalVotingPower();
proposals[proposalId].totalVotingPowerAtCreation = totalVotingPower;
// ... other logic ...
}
// Update the quorum function to use the stored value
function quorum(uint256 proposalId) public view returns (uint256) {
return (proposals[proposalId].totalVotingPowerAtCreation * quorumNumerator) / QUORUM_DENOMINATOR;
}

This change ensures that the quorum requirement remains stable and reflects the governance intent at the time of proposal creation, thus preventing manipulation through changes in total voting power during the voting period.


Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months 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 3 months 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.