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

Based on The developers flow a user should claim his rewards immediately he unstakes but we Fail to Claim Rewards Upon Unstaking in Staking Contract

Summary

The current implementation of the staking contract allows users to unstake their tokens without automatically claiming their pending rewards. This issue can lead to a scenario where users, who would normally incur a penalty for early unstaking and reward claiming, can bypass the penalty. As a result, users may unintentionally or deliberately avoid paying the penalty

Vulnerability Details

The unstaking process in the contract does not automatically trigger a reward claim, even though the unstake action should ideally be coupled with an immediate reward claim. The relevant part of the unstaking function is as follows:

/// @notice Unstake FJORD tokens from the contract.
/// @dev This function allows users to unstake a certain number of FJORD tokens,
@ audit>>>> /// while also claiming all the pending rewards. If \_isEarly is true then the
@ audit>>>> /// user will be able to bypass rewards cooldown of 3 epochs and claim early,
/// but will incur early claim penalty.
/// @param \_epoch The epoch cycle from which user wants to unstake.
/// @param \_amount The amount of tokens user wants to unstake.
/// @return total The total amount sent to the user.
function unstake(uint16 \_epoch, uint256 \_amount)
external
checkEpochRollover
redeemPendingRewards
returns (uint256 total)
{
// (Logic for unstaking)
total = \_amount;
//INTERACT
fjordToken.safeTransfer(msg.sender, total);
points.onUnstaked(msg.sender, \_amount);
emit Unstaked(msg.sender, \_epoch, \_amount);
}

The function is designed to transfer the unstaked tokens back to the user and record the unstake event. However, there is no direct call to claim the user's rewards immediately after unstaking. This omission allows users to unstake their tokens without claiming their pending rewards, effectively evading the early claim penalty.

Additionally, the `claimReward` function checks whether the user wants to claim early and applies a penalty accordingly:

/// @notice Claim reward from specific epoch.
/// @dev This function allows users to claim rewards from an epoch,
/// if the user chooses to bypass the reward cooldown of 3 epochs,
/// then reward penalty will be levied.
/// @param \_isClaimEarly Whether user wants to claim early and incur penalty.
/// @return rewardAmount The reward amount that has been distributed.
/// @return penaltyAmount The penalty incurred by the user for early claim.
function claimReward(bool \_isClaimEarly)
external
checkEpochRollover
redeemPendingRewards
returns (uint256 rewardAmount, uint256 penaltyAmount)
{
// (Logic for claiming rewards)
}

Since the `claimReward` function is separate from the `unstake` function, a user who unstakes but does not call `claimReward` immedaitely can avoid paying the early claim penalty.

Impact

This vulnerability enables users to bypass the penalty for early reward claiming by unstaking their tokens without immediately claiming their rewards.

Tools Used

Manual Code Review

Recommendations

1. **Enforce Immediate Reward Claim on Unstaking**: Modify the `unstake` function to include an automatic call to the `claimReward` function, ensuring that users cannot unstake without claiming their rewards. This will enforce the early claim penalty as intended.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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