Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

after 1st time/2nd time distributing rewards to a gauge, function distributeRewards will revert for that gauge and rewards can’t be distributed to that gauge.

Summary

when the function updatePeriod is called for a gauge in the GaugeController contract, the gauge contract’s function updatePeriod is not called. The gauge contract’s function updatePeriod can only be called by the GaugeController contract. But The gauge contract’s function updatePeriod is not called anywhere in the GaugeController contract. As a result, after 1st time/2nd time distributing rewards to this gauge by the GaugeController contract, the gauge contract’s periodState.distributed will be equal to periodState.emission. When The gauge contract’s function updatePeriod is called, periodState.distributed is set to 0. As The gauge contract’s function updatePeriod is not called anywhere, so periodState.distributed will be equal to periodState.emission. Now when in the next period, the function distributeRewards is called for this gauge, this calls gauge contract’s function notifyReward where amount + state.distributed > state.emission) {

** revert RewardCapExceeded();**

So the function distributeRewards will revert because amount + state.distributed>.state.emission.

\

Vulnerability Details

1. Let’s assume a gauge’s (assume gauge1) periodState.emission = 250000e18. function distributeRewards is called in the GaugeController contract for this gauge1 to notify rewards with 250000e18 reward amounts. Now gauge1’s periodState.distributed is updated to 250000e18.

2. after that, as period.totalDuration for gauge1 is ended so the function updatePeriod in the GaugeController contract for this gauge1 is called and a new period is started for this gauge1. But gauge1 contract’s function updatePeriod is not called to update period . gauge1 contract’s function updatePeriod can only be called by GaugeController contract. periodState.distributed is set to 0 when gauge1 contract’s function updatePeriod is called.

3. as gauge1 contract’s function updatePeriod is not called by the GaugeController contract so periodState.distributed is still 250000e18.

4. now function distributeRewards is again called for the new period in the GaugeController contract for this gauge1 to notify rewards with 250000e18 reward amounts. Here function distributeRewards calls gauge1’s function notifyReward where amount + state.distributed is greater than state.emission i.e 250000e18+250000e18 = 500000e18 > 250000e18( as periodState.emission is set 250000e18 ).so calling function notifyReward will revert as if (amount + state.distributed > state.emission) {

** revert RewardCapExceeded()**

Impact

** when the function updatePeriod is called for a gauge in the GaugeController contract, the gauge contract’s function updatePeriod is not called. As a result, after 1st time/2nd time distributing rewards to this gauge, function distributeRewards will revert and rewards can’t be distributed to that gauge.**

Tools Used

manual review

Recommendations

when the function updatePeriod is called for a gauge in the GaugeController contract, the gauge contract’s function updatePeriod should be called/updated.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController::updatePeriod doesn't call the gauge's updatePeriod function, preventing periodState.distributed from resetting and eventually causing distributeRewards to permanently fail

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController::updatePeriod doesn't call the gauge's updatePeriod function, preventing periodState.distributed from resetting and eventually causing distributeRewards to permanently fail

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!