The vulnerability lies in the fact that during the 7-day
voting period, any proposal can be canceled if the proposer's voting power falls below the required threshold. This means that even if a proposal was valid at creation, it becomes vulnerable to cancellation within that period if the decaying voting power causes it to drop below the threshold.
When a proposal is created, the contract checks that the caller’s current voting power meets proposalThreshold
:
Governance::propose()
Requirement: The proposer must have at least proposalThreshold
(e.g., 100,000 veRAAC tokens).
Later, when attempting to cancel a proposal, the contract includes the following logic:
Cancellation Condition: Anyone (other than the proposer) can cancel the proposal if the proposer's current voting power is below the proposalThreshold
.
veRAACToken
The voting power is calculated based on a point system with a bias (initial power) and a slope (rate of decay):
Key Math:
Initial Setup:
A user mints 100,000e18
tokens for 4 years.
The voting power (bias) is calculated as:
Time Decay Effect:
Consider the scenario where:
The proposal is created with block.timestamp = T
.
The proposal have 7 days Duration of voting period
The tokens were minted at T
(i.e., point.timestamp = T
seconds).
The voting power at the moment of cancellation (at time T + 7
) is computed as:
timeDelta = 604800
decay = slope * timeDelta
(≈ 792744799594114 * 604800)
adjustedBias = bias - decay
With these values, even though the proposer initially had exactly 100,000e18 voting power, by the time of cancellation, the decayed voting power drops to a value less than the threshold (e.g., approximately 99,520e18
).
Initial Setup:
A user locks 100,000e18 tokens for 4 years. At the moment of minting, the user’s voting power equals the threshold (100,000e18).
Proposal Creation:
The user creates a proposal. The check in the propose
function passes because the user’s voting power meets the threshold.
Time Decay:
Due to the linear decay mechanism, after a period (e.g., after 7 days—the duration used in the calculation), the voting power decays by an amount proportional to the time elapsed.
Unauthorized Cancellation:
At a later time, when a third party (not the proposal creator) calls the cancel
function:
The contract re-checks the proposer's voting power using the decayed value.
Since the decayed voting power is now below proposalThreshold
, the check:
is bypassed.
Result: The proposal is canceled even though it was valid at creation.
Valid proposals can be canceled by anyone once the proposer’s voting power decays below the threshold, undermining the governance process.
Proposers might be discouraged from participating if their proposals can be canceled due to natural decay, even if they initially met the requirements.
Manual Review
Consider recording the proposer’s voting power at the time of proposal creation and use that static value for later checks (e.g., in cancellation logic) rather than recalculating it with a decay factor.
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.