The Governance.sol contract allows the owner to update the quorumNumerator, which retroactively alters the quorum requirements for all proposals, even after voting ends. This can cause a previously successful proposal to fail.
This issue is because the quorumNumerator, which determines the percentage of total voting power needed for a proposal to reach quorum, is dynamically applied to all proposals whenever their state is checked. This parameter is initially set to 4 (representing a 4% quorum) but can be modified by the owner through the setParameter function. The issue is that the state function uses the current quorumNumerator value to evaluate a proposal’s success, not the value in place when the proposal was created or voted on.
Below is the state function, which determines a proposal’s status after voting
state doesn’t lock in the quorumNumerator from the proposal’s voting period. Instead, it fetches the current value, allowing updates to retroactively rewrite outcomes.
Imagine a proposal with a total voting power of 100M veRAAC tokens. During voting, quorumNumerator is 4, so the quorum is 4M (4% of 100M). The proposal receives 5M votes (3M “for,” 2M “against”), exceeding the 4M quorum and passing with more “for” votes. Voting ends, and the proposal enters the Succeeded state, awaiting queuing in the timelock. Later, the owner updates quorumNumerator to 5, making the quorum 5M (5% of 100M). When someone calls state to queue or execute it, currentQuorum (5M) is now exactly equal to requiredQuorum (5M), but if total voting power shifts slightly (e.g., to 110M due to new locks), the quorum becomes 5.5M, and the proposal fails (5M < 5.5M) despite passing earlier.
This isn't about trust, it's about maintaining consistent, predictable governance mechanics. The owner's ability to change future quorum requirements is fine, but those changes shouldn't affect proposals that already completed voting.
A trusted owner might update quorumNumerator for a legitimate reason (e.g., adapting to a 5% increase in voting power) without realizing it affects queued proposals.
Proposals that were initially successful may fail later due to external changes in voting power.
Voters cannot rely on the fairness of the governance system since rules can be altered retroactively.
Manual Review
To fix this, the Governance.sol should be modified to snapshot the quorumNumerator for each proposal at creation. Add a quorumNumerator field to the ProposalCore struct.
Update the propose function to store it
Adjust state to use the stored value
Alternatively, restrict setParameter to only affect future proposals by checking active proposal states, though the snapshot approach is simpler and more robust.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.