The unstake function in the FjordStaking has a logic flaw when handling unstaking in the current epoch. This is because the contract only decreases newStaked and doesn't update totalStaked or userData[msg.sender].totalStaked when a user unstakes in the current epoch. Malicious users could use this to game the protocol to receive more rewards than intended as rewards are distributed based on the totalStaked value
The unstake function goes thus:
Now here's where the main issue emanates from. When a user unstakes tokens in the current epoch, the contract only decreases newStaked and DOESN'T update totalStaked or userData[msg.sender].totalStaked.
Lets consider 2 scenarios. 1st scenario will be Unstaking in a previous epoch and the second will be Unstaking in the current epoch
Alice stakes tokens:
Alice stakes 100 tokens in epoch 1.
totalStaked is increased by 100.
userData[msg.sender].totalStaked is increased by 100.
Alice unstakes tokens in epoch 2:
Alice unstakes 50 tokens in epoch 2.
totalStaked is decreased by 50.
userData[msg.sender].totalStaked is decreased by 50.
In this scenario, the accounting is correct because both totalStaked and userData[msg.sender].totalStaked are updated.
Bob stakes tokens:
Bob stakes 100 tokens in epoch 1.
totalStaked is increased by 100.
userData[msg.sender].totalStaked is increased by 100.
Bob unstakes tokens in the same epoch:
Bob unstakes 50 tokens in epoch 1.
newStaked is decreased by 50.
totalStaked and userData[msg.sender].totalStaked are not updated.
Here in this scenario, the accounting is INCORRECT because totalStaked and userData[msg.sender].totalStaked are not updated. So therefore:
This ccauses an inflated totalStaked value. The totalStaked value remains higher than the actual staked amount. This will cause incorrect reward calculations, as rewards are distributed based on the totalStaked value
Also, the user's totalStaked amount is not reduced, even though they have unstaked tokens therefore causing inconsistencies in the user's staking data.
In simpler terms, Bob(in our case) could exploit this to receive more rewards than he deserves. For example:
Bob stakes and unstakes in the same epoch
Bob stakes 100 tokens in epoch 1.
Bob unstakes 100 tokens in epoch 1.
As for the reward calculation,
The totalStaked value remains 100, even though Bob has unstaked all their tokens.
Rewards are calculated based on the inflated totalStaked value, leading to higher rewards for Bob.
Protocol could end up with incorrect reward calculations and potential exploitation by users such as Bob to receive more rewards than intended as rewards are distributed based on the totalStaked value.
Manual
Both newStaked and totalStaked (along with the user's total staked amount) should be updated when unstaking in the current epoch.
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.