The reward distribution mechanism in GaugeController::_distributeToGauges allocates 80% of gauge shares based on each gauge's weight. Each gauge has an emissionCap, which limits its total distributed rewards. However, GaugeController::_distributeToGauges does not check these caps before distributing rewards. If a single gauge exceeds its emissionCap, the entire transaction reverts, preventing all gauges from receiving their share.
While BaseGauge::updatePeriod, callable only by GaugeController, can reset a gauge’s distributed rewards to 0, this function is never invoked within GaugeController, effectively making the distribution mechanism DoSed.
Here is GaugeController::_distributeToGauges
The function traverses the gauges array and distributes the gauge share amounts to the corresponding gauges via BaseGauge::notifyRewardAmount.
This function accumulates distributed rewards into periodState.distributed and checks if the new total exceeds emissionCap:
If amount + state.distributed exceeds emissionCap, execution reverts, causing GaugeController::_distributeToGauges to fail entirely.
Since BaseGauge::updatePeriod (which resets periodState.distributed to 0) is never called within GaugeController, the issue persists indefinitely, rendering GaugeController::distributeRevenue non-functional.
GaugeController::distributeRevenue is responsible for allocating 80% of rewards to gauges through _distributeToGauges. Since the function can be DoSed due to unhandled emissionCap limits, this substantial share of rewards could remain undistributed, severely impacting the protocol's reward distribution mechanism.
Manual Review, VSCode
Modify GaugeController to invoke BaseGauge::updatePeriod when a gauge reaches its emissionCap.
Add a function in GaugeController.sol to allow manual resetting:
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.