The notifyRewardAmount function in BaseGauge contract is used to adjust the rewardRate by distributing a specified amount of rewards. However, there is a discrepancy between the actual rewards distributed and the value stored in state.distributed. This inconsistency arises because state.distributed is incremented by the amount passed to notifyRewardAmount, but the actual rewards distributed depend on the rewardRate and the duration of the period. If notifyRewardAmount is called multiple times, state.distributed may not accurately reflect the true amount of rewards distributed, leading to potential issues in reward accounting and distribution.
The notifyRewardAmount function updates the rewardRate and increments state.distributed by the amount provided. Here is the relevant code:
The notifyReward function calculates the rewardRate based on the amount and the period duration. Here is the relevant code:
Every time notifyRewardAmount is called, state.distributed is incremented by the amount passed to the function. This assumes that the entire amount will be distributed immediately, which is not the case. However, the actual rewards distributed depend on the rewardRate and the duration of the period. The rewardRate is calculated as amount / periodDuration, meaning the rewards are distributed gradually over the period. If notifyRewardAmount is called multiple times within a single period, the rewardRate is updated, but the actual rewards distributed may not match the sum of the amounts passed to notifyRewardAmount.
Example Scenario
First Call to notifyRewardAmount:
amount = 1000
periodDuration = 7 days
rewardRate = 1000 / 7 days ≈ 142.857 per day
state.distributed = 1000
Second Call to notifyRewardAmount (after 3 days):
amount = 1000
rewardRate = 1000 / 7 days ≈ 142.857 per day
state.distributed = 1000 + 1000 = 2000
Actual Rewards Distributed:
After 3 days, the first rewardRate would have distributed 142.857 * 3 ≈ 428.571.
The second rewardRate would distribute 142.857 * 4 ≈ 571.428 over the remaining 4 days.
Total rewards distributed: 428.571 + 571.428 ≈ 1000
However, state.distributed is 2000, which is double the actual rewards distributed.
Inaccurate Reward Accounting:
state.distributed does not reflect the actual rewards distributed, leading to discrepancies in the protocol's accounting.
Potential Overestimation of Rewards:
If notifyRewardAmount is called multiple times, state.distributed may exceed the actual rewards distributed, causing the protocol to overestimate the rewards.
Reward Distribution Issues:
The discrepancy between state.distributed and the actual rewards distributed can lead to incorrect reward calculations, potentially causing users to receive fewer rewards than expected.
The impact is Medium, the likelihood is Medium, so the severity is Medium.
Manual Review
Instead of incrementing state.distributed by the amount passed to notifyRewardAmount, track the actual rewards distributed based on the rewardRate and the time elapsed since the last update.
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.