The BaseGauge
contract's reward calculation allows any futures staker to be rewarded with rewardPerTokenStored
that have been accumulated since creation of contract. That means a user who hasn't been staking from the beginning will be rewarded the same as a user who has been staking since the beginning. Or in other words the contract assumes that every user staked when the rewardPerTokenStored
is 0.
rewardPerToken
Accumulation: The rewardPerToken
value increases over time as rewards are distributed and staking occurs. This value persists even if no new rewards are being distributed.
Instant Benefit for New Stakers: When a new user stakes tokens, their rewardPerTokenPaid
is always set after calculating the earned rewards. Thus new stakers instantly benefit from this accumulated rewardPerToken
, even if no new rewards have been distributed since the previous user staked.
Not Accounting Already Accumulated rewardPerTokenStored
: The rewardPerTokenStored
should be updated before calculating the rewards for new stakers. This would ensure that new stakers only receive rewards based on the rewardPerTokenStored
value at the time of staking, rather than benefiting from previously accumulated rewards.
Unfair Reward Distribution: Future stakers receives rewards based on the already accumulated rewardPerToken
, while earlier stakers are penalized for their early participation. This creates an unfair and inequitable reward system.
Insufficient rewards for early stakers: Early stakers receive fewer rewards than they should, as the rewards are distributed based on the accumulated rewardPerTokenStored
value, rather than the value at the time of staking. This causes a loss of rewards for early participants, also no incentive for early staking.
Scenario:
Alice stakes 100 tokens in the BaseGauge
contract when rewardPerTokenStored
is 0. She earns some rewards over time.
Bluedragon waits until rewardPerTokenStored
has increased to 1000 before staking 100 tokens.
Bluedragon's rewardPerTokenPaid
is set to 0 when they stake, and they instantly benefit from the accumulated rewards based on the rewardPerTokenStored
value of 1000.
Alice, who has been staking since the beginning, receives rewards based on the rewardPerTokenStored
value of 1000, but she has been staking since the rewardPerTokenStored
was 0.
Bluedragon gains more rewards than Alice instantly, even though Alice has been staking longer.
Use this guide to intergrate foundry into your project: foundry
Create a new file FortisAudits.t.sol
in the test
directory.
Add the following gist code to the file: Gist Code
Run the test using forge test --mt test_FortisAudits_FutureStakersEarnsMoreThanEarlyStakers -vvvv
.
Manual code review
To address this vulnerability, the rewardPerTokenPaid
value should be updated to the current rewardPerTokenStored
value when a user stakes tokens. This ensures that new stakers only receive rewards based on the current rewardPerTokenStored
value, rather than benefiting from previously accumulated rewards.
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.