Summary
The distributeRevenue function updates accounting variables but does not execute any token transfers to actually distribute the revenue to gauges or veToken holders.
Vulnerability Details
The function is incomplete in that it only adjusts variables; it does not call methods to transfer ERC20 tokens from the contract’s balance to the intended recipients or trigger a distribution mechanism.
distributeRevenue is intended to @notice Distributes revenue between veToken holders and gauges ->
-> There is no mechanism to transfer revenue to VeToken holders
function distributeRevenue(
GaugeType gaugeType,
uint256 amount
) external onlyRole(EMERGENCY_ADMIN) whenNotPaused {
if (amount == 0) revert InvalidAmount();
uint256 veRAACShare = amount * 80 / 100;
uint256 performanceShare = amount * 20 / 100;
revenueShares[gaugeType] += veRAACShare;
_distributeToGauges(gaugeType, veRAACShare);
emit RevenueDistributed(gaugeType, amount, veRAACShare, performanceShare);
}
* @notice Distributes rewards to gauges of a specific type
* @dev Internal function to handle gauge reward distribution
* @param gaugeType Type of gauges to distribute to
* @param amount Total amount to distribute
*/
function _distributeToGauges(
GaugeType gaugeType,
uint256 amount
) internal {
uint256 totalTypeWeight = 0;
uint256[] memory gaugeWeights = new uint256[](_gaugeList.length);
uint256 activeGaugeCount = 0;
for (uint256 i = 0; i < _gaugeList.length; i++) {
address gauge = _gaugeList[i];
if (gauges[gauge].isActive && gauges[gauge].gaugeType == gaugeType) {
gaugeWeights[i] = gauges[gauge].weight;
totalTypeWeight += gaugeWeights[i];
activeGaugeCount++;
}
}
if (totalTypeWeight == 0 || activeGaugeCount == 0) return;
for (uint256 i = 0; i < _gaugeList.length; i++) {
address gauge = _gaugeList[i];
if (gauges[gauge].isActive && gauges[gauge].gaugeType == gaugeType) {
uint256 gaugeShare = (amount * gaugeWeights[i]) / totalTypeWeight;
if (gaugeShare > 0) {
IGauge(gauge).notifyRewardAmount(gaugeShare);
}
}
}
}
Further calls that results in notifyRewardAmount function which itself lacks token transfers to both gauges and token holders
Impact
If revenue tokens are not physically transferred to the appropriate recipients, then despite the internal accounting reflecting that revenue has been distributed, the funds remain locked in the contract. This failure undermines the reward distribution mechanism, potentially leading to a loss of earned revenue.
Recommendations
Integrate token transfer logic into the distributeRevenue function for both to token holders and to the gauges.