The Governance
contract's dynamic quorum calculation can prevent the execution of proposals that previously passed voting and are queued for execution.
The execute
function is called twice - once to queue a proposal in TimelockController
and once to execute the queued proposal. Before each operation in execute
, the state of the proposal is checked.
The issue arises from recalculating quorum every time state
is called:
A proposal that already passed and is in the queued state (quorum met once and ready for execution), cannot be executed due to checking the state (recalculating quorum) again in execute
before executing:
The quorum
function always returns 4% of the current total supply of veRAAC:
Example scenario:
Total voting power = 1,000
Quorum = 40 (4%)
Proposal receives 50 votes (passes quorum) and is queued for execution
Total voting power increases to 2,000
New quorum = 80
Before _executeProposal
in execute
is called, state
sees 50 < 80
Proposal becomes unexecutable despite previously passing
After voting ends, currentQuorum
cannot change, but requiredQuorum
is dynamic. Large locks in veRAACToken
can significantly inflate requiredQuorum
.
High: Proposals that successfully passed voting can become unexecutable due to changes in total voting power. This prevents critical governance actions, potentially leaving the protocol in a stuck state.
Consider calculating and storing the quorum for a proposal only when creating the proposal or when queuing it.
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.