According to the comment, admin must call addReward()
so that rewards are distributed immediately.
However, by chance or due to front-run, the rewards may not be distributed inside the addReward()
.
Therefore, rewards are distributed incorrectly per epoch to stakers.
The relevant code of FjordStaking.addReward()
is following.
According to the comment of L752
, admin must only call addReward()
if it can trigger update next epoch. It ensures that the _amount
of rewards are transferred from the admin to the contract in L763
and are distributed to stakers in the following _checkEpochRollover()
of L765
.
However, it may not always be the case.
If stakers call stake()
, unstake()
, stakeVested()
or unstakeVested()
, it calls internally _checkEpochRollover()
which will update epoch to next epoch if possible.
Even though the admin calls addReward()
at the begining of epoch, there can be a user's tx before admin's tx to update the epoch to next epoch. The more stakers exist, the higher the possibility will be.
The following Scenario is available:
Assume that admin calls repeatedly addReward()
by passing _amount = 10 ether
at the begining of each epoch.
At epoch 1, admin calls addReward()
. Then 10 ether
of rewards will be distributed at epoch 1.
At epoch 2, user A calls addReward()
. Unfortunately, a staker's stake()
tx is executed before admin's addReward()
tx. Since the current epoch is updated in staker's tx, the _amount
of rewards of admin's tx can't be distributed at epoch 2.
At epoch 3, admin calls addReward()
again. Then 20 ether
of rewards which are sum of rewards for epoch 2 and epoch 3 will be distributed at a time at epoch 3.
As shown above, the rewards are distributed 10 ether
for epoch 1, zero for epoch 2, and 20 ether
for epoch 3. That is, the rewards are distributed incorrectly per epoch.
Note:
Exploiting this vulnerability, attacker can front-run the admin's tx and change the rewards distribution to be in favor of himself.
Rewards are distributed incorrectly to stakers.
Attacker can front-run the admin's tx and change the rewards distribution to be in favor of himself.
Manual Review
It is recommended to change the order of fjordToken.safeTransferFrom()
and _checkEpochRollover()
in FjordStaking.addReward()
.
Then, the rewards will be distributed correctly per epoch regardless of the presence of staker's tx.
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.