Summary
The GaugeController
's vote()
function only verifies if a gauge exists but fails to validate if the gauge is active. This oversight allows users to vote on inactive gauges, leading to reward distribution issues and manipulation of the gauge weight system.
Vulnerability Details
The vote()
function in GaugeController
implements the following checks:
function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
uint256 votingPower = veRAACToken.balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
}
The issue arises because the Gauge struct (from IGaugeController) includes an isActive
flag:
struct Gauge {
uint256 weight;
uint256 typeWeight;
uint256 lastUpdateTime;
GaugeType gaugeType;
bool isActive;
uint256 lastRewardTime;
}
but the vote()
function only checks if the gauge exists via isGauge()
but not if it's active.
Other functions in the contract, like updatePeriod()
, properly check for gauge activity:
function updatePeriod(address gauge) external override whenNotPaused {
Gauge storage g = gauges[gauge];
if (!g.isActive) revert GaugeNotActive();
...
}
Impact
Users can continue voting on inactive gauges. These votes affect the global weight distribution. When rewards are distributed, the weights of inactive gauges are still counted, skewing the distribution for active gauges.
Tools Used
Manual Review
Recommendations
function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
+ if (!gauges[gauge].isActive) revert GaugeNotActive();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
uint256 votingPower = veRAACToken.balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
}