The GaugeController manages reward distribution to various gauges in the system. Each gauge has a period mechanism that tracks distributed rewards and enforces reward caps. The BaseGauge contract implements the core period and reward distribution logic.
The GaugeController#updatePeriod function fails to call IGauge(gauge).updatePeriod() when rolling over to a new period. This means the gauge's internal period state, specifically periodState.distributed, is never reset to 0.
Furthermore, the architecture provides no mechanism for the controller to trigger a gauge's period update - the updatePeriod function in GaugeController only updates its own internal period tracking, but has no way to trigger the corresponding update in the gauge contract.
In BaseGauge, the notifyRewardAmount function enforces that total distributed rewards cannot exceed the period emission cap through the check:
Since distributed is never reset, it will eventually reach the emission cap, causing all subsequent reward distributions to revert.
High. Once a gauge's distributed amount reaches the emission cap, that gauge can no longer receive any rewards. This effectively breaks the core reward distribution mechanism for affected gauges. The issue is particularly severe because there is no architectural pathway to trigger a period reset from the controller.
High. This will affect every gauge once enough rewards have been distributed to reach their emission caps. The issue is deterministic and will occur in normal operation of the protocol.
A gauge is added to the system with an emission cap of 1000 tokens per period
Over several reward distributions, periodState.distributed accumulates to 900 tokens
Controller attempts to distribute 200 more tokens via notifyRewardAmount
Transaction reverts because 900 + 200 > 1000 (emission cap)
All subsequent reward distributions to this gauge will fail
Due to architectural limitations, there is no way for the controller to reset the gauge's period state
The system needs both an immediate fix and an architectural improvement:
Add a method to trigger gauge period updates:
Modify GaugeController#updatePeriod to use this interface:
This ensures proper synchronization between controller and gauge periods, allowing the reward distribution system to function as intended.
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.