The Staking::deposit
function allows the user who have LoveTokens
to deposit amount of them and then to claim rewards based on the amount and the staked time. But if more people deposit large amount of tokens the total supply of stakingVault
would be not enough to cover all rewards.
The Staking::deposit
function allows the user who have LoveTokens
to deposit amount of them and then to claim rewards based on the amount and the staked time. The function makes check if the balance of stakingVault
is not zero. But this check does not guarantee that there will be enough rewards for all future claims, especially if many users are staking large amounts of tokens. It only ensures that at the moment of deposit, the stakingVault
is not completely empty.
Let's consider a scenario where the stakingVault
has a non-zero balance that is not sufficient to cover the potential future rewards for all staked tokens, and a user tries to make a deposit. Assume the following:
The stakingVault contains 200 LoveToken
to be distributed as rewards. There are 5
users who have each staked 50 LoveToken
. According to the reward policy, users can claim 1 LoveToken
per staked token per week. A new user, Charlie, wants to deposit 100 LoveToken
into the Staking
contract. Here's what happens:
Charlie calls Staking::deposit
function with amount
equals to 100
.
The Staking
contract checks the balance of the stakingVault
:
Since the stakingVault
balance is 200 LoveToken
, which is not zero, the deposit function proceeds without reverting.
Charlie's deposit is successful, and his 100 LoveToken
are transferred to the Staking
contract. The userStakes
mapping is updated to reflect Charlie's stake.
Now, if a week passes and all users, including Charlie, try to claim their rewards and no new users are deposited:
The total staked tokens are now 350 LoveToken
(5 existing users * 50 loveToken each + Charlie's 100 loveToken).
The total rewards to be claimed by all users would be 350 LoveToken
if each user claims for one week.
But the stakingVault
only has 200 LoveToken
available for rewards.
When users start claiming their rewards, the stakingVault
will be depleted before all users have claimed their due rewards. The first two users to claim would receive their full rewards (100 LoveToken
each), but the other users would receive nothing because the transferFrom
function will revert due to arithmetic underflow or overflow
.
Also, if the stakingVault
has some amount of tokens but not enough for rewards, these tokens will be left in the contract. It is better to have a dust collector like in the Airdrop::claim
function.
The Staking::deposit
function does not account for the future obligations of the contract based on the current staking balance and the rewards policy.
Manual Review
The contract should implement a more sophisticated check that considers the total staked tokens and the duration of the staking to ensure that the stakingVault
has enough funds to cover the rewards for all staked tokens, not just at the time of deposit but also for the foreseeable future.
Also, add a dust collector to the Staking::claimRewards
function. In that way no amount would be left in the stakingVault
.
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.