DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

Users Can Stake Tokens Without Earning Rewards

Summary

A vulnerability has been identified in the staking contract that allows users to stake their tokens without receiving any rewards. This issue occurs when the admin has not added any rewards, causing the contract to fail in calculating pending rewards, which results in users staking their tokens for 0 reward. The problem stems from the improper handling of epoch rollover logic, leading to incorrect reward calculations.

Vulnerability Details

The staking contract manages staked tokens using two variables: newStaked and totalStaked. These track tokens staked via the stake() and stakeVested() functions. When a new epoch is triggered, the tokens in newStaked are transferred to totalStaked, meaning that newStaked only contains tokens staked in the current epoch, while totalStaked reflects all tokens staked in previous epochs. Similarly, tokens staked via stakeVested() are recorded in newVestedStaked, and upon an epoch increment, these tokens are moved to totalVestedStaked.
This ensures that the total staked tokens (across both normal and vested staking) align with the contract's actual token balance(fjordToken.balanceOf(address(this))) + totalVested + newVested. Keep in mind that the balance(fjordToken.balanceOf(address(this)) should contain the rewards if they are added by the admin.

The vulnerability arises during the epoch rollover, which can be triggered by any user interacting with functions that use the checkEpochRollover modifier (e.g., stake(), stakeVested(), unstake()). If the epoch is incremented without the admin first calling addReward(), stakers will be left without rewards. Since the balance of staked tokens must be equal the sum of totalStaked and newStaked, the result of pendingRewards becomes 0. Consequently, the reward per token (rewardPerToken) does not change between epochs. This leads to improper reward calculation because the reward amount is determined by the difference between the reward per token in two epoch.

function calculateReward(uint256 _amount, uint16 _fromEpoch, uint16 _toEpoch)
internal
view
returns (uint256 rewardAmount)
{
@> rewardAmount =
@> (_amount * (rewardPerToken[_toEpoch] - rewardPerToken[_fromEpoch])) / PRECISION_18;
}

Impact

Users will be unable to claim any rewards for their staked tokens if the staking admin fails to add rewards. This flaw renders the staking process ineffective.

Tools Used

Manual review

Recommendations

Implement a validation mechanism that ensures that users cannot stake their tokens without reward added by the administrator for the current epoch. If you want to keep staking without reward possible, users must be clearly informed for the lack of rewards before proceeding with staking.

Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

julianavantgarde Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.