Users receive double rewards.
Insolvency occurs as early users claim double rewards, causing later transactions to revert due to insufficient tokens in the contract.
If an epoch is missed, later when it's rolled users will earn double rewards. Missing an epoch can occur due to the system being new and few users having familiarity with it or any other reason.
_checkEpochRollover is used to advance epochs, calculate rewards for each epoch, and update global values like totalRewards. The function includes a for loop that updates all missed epochs:
Note that lastEpochRewarded is always set to currentEpoch - 1, meaning that if the function is invoked mid-epoch 6, it will calculate rewards up to epoch 5.
However, this for loop inflates the rewards by adding the pendingRewardsPerToken generated up to now to every missed epoch. If one epoch is missed, pendingRewardsPerToken would be doubled; if two are missed, it would be tripled, and so on.
This issue occurs because the total pendingRewardsPerToken generated from the last triggered epoch is calculated:
But it is then incorrectly added to every missed epoch:
Example (1 missed epoch):
The last triggered epoch was X (meaning lastEpochRewarded = X-1) with rewardPerToken = 100.
We are now at X+2 with 10 pendingRewardsPerToken generated from X to X+2.
The for loop will perform the following:
The for loop inside _checkEpochRollover incorrectly adds the entire balance for all missed epochs.
Manual review.
Instead of adding the total rewards to every epoch, only add them to the current one.
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.