Different contracts in the system fetch and calculate voting power using the veRAACToken::getVotingPower()
function. This approach is correctly followed by FeeCollector
, BoostController
, and Governance
contracts. However, an issue was found in GaugeController::vote()
and BaseGauge::voteDirection()
, where voting power is calculated differently.
Instead of using veRAACToken::getVotingPower()
, GaugeController::vote()
and BaseGauge::voteDirection()
incorrectly calculate voting power based only on the user's**** veRAACToken
balance.
function voteDirection(uint256 direction) public whenNotPaused updateReward(msg.sender) {
if (direction > 10000) revert InvalidWeight();
This is not correct because getVotingPower()
uses VotingPowerLib::getCurrentPower()
to determine voting power. This function not only considers the token balance but also accounts for how long the tokens have been locked.
By relying solely on token balance, vote()
and voteDirection()
allow users to manipulate the system by accumulating a large number of tokens just before voting. This creates an unfair advantage, as new token holders can significantly influence voting outcomes, while long-term token holders lose their intended weight in governance decisions.
High. Attacker can unfairly influence votes by temporarily acquiring a large balance. Long-term token holders are disadvantaged, undermining the intended governance mechanism.
Update GaugeController::vote()
and BaseGauge::voteDirection()
to use getVotingPower()
instead relying on balanceOf(user)
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.