sherlock-audit / 2024-05-gamma-staking-judging

9 stars 7 forks source link

fandonov - The users balance is not set to 0 after he gets his rewards. #217

Closed sherlock-admin4 closed 5 months ago

sherlock-admin4 commented 6 months ago

fandonov

high

The users balance is not set to 0 after he gets his rewards.

Summary

The user will still have the same lockedWithMultiplier balance even after he gets his rewards transferred to him via the getReward function.

Vulnerability Detail

There is no check in the functions if the user called exitLateById or earlyExitById prior to calling this function or if the 30-day period has passed, so the user will be able to call the getReward function whenever he wants because it's a public function. When the user calls the getReward function he wants to get his rewards. This function first calls the _updateReward function which updates his earnings with the _earned function. The problem lies here because he gets his earnings set to a specific amount with this math earnings = rewardInfo.cumulatedReward * balance.lockedWithMultiplier - rewardDebt[_user][_rewardToken]; but the balance.lockedWithMultiplier is never set to 0 in this function so the user will still have his funds that are locked with a multiplier. This is the whole function:

 function _earned(
        address _user,
        address _rewardToken
    ) internal view returns (uint256 earnings) {
        Reward memory rewardInfo = rewardData[_rewardToken]; // Retrieves reward data for the specified token.
        Balances memory balance = balances[_user]; // Retrieves balance information for the user.
        earnings = rewardInfo.cumulatedReward * balance.lockedWithMultiplier - rewardDebt[_user][_rewardToken]; // Calculates earnings by considering the accumulated reward and the reward debt.
    }

After this, the getReward function calls the _getReward function which is represented in the next way:

function _getReward(
        address _user,
        address[] memory _rewardTokens
    ) internal whenNotPaused {
        uint256 length = _rewardTokens.length; // Get the number of reward tokens to process.
        for (uint256 i = 0; i < length; ) {
            address token = _rewardTokens[i]; // Get the current token address.

            uint256 reward = rewards[_user][token]; // Retrieve the amount of reward due for the user and the token.
            if (reward > 0) {
                rewards[_user][token] = 0; // Reset the reward to zero after claiming.
                rewardData[token].balance -= reward / 1e36; // Deduct the reward from the stored balance, adjusting for decimals.

                IERC20(token).safeTransfer(_user, reward / 1e36); // Transfer the reward to the user.
                rewardPaid[_user][token] += reward / 1e36; // Update the total reward paid to the user for this token.  
                emit RewardPaid(_user, token, reward / 1e36); // Emit an event documenting the reward payment.
            }
            unchecked {
                i++;
            }
        }
    }

As we can see this function sets the rewards for the user to 0 but that still doesn't set his lockedWithMultiplier balance to 0 so after some time if the user calls getReward again he will be able to withdraw a reward again.

Impact

The user will be able to withdraw his rewards and still have the balance he previously had prior to getting his rewards.

Code Snippet

https://github.com/sherlock-audit/2024-05-gamma-staking/blob/703fd3604069489937037f20490ec8c492c0508e/StakingV2/src/Lock.sol#L526-L529

https://github.com/sherlock-audit/2024-05-gamma-staking/blob/703fd3604069489937037f20490ec8c492c0508e/StakingV2/src/Lock.sol#L614-L629

https://github.com/sherlock-audit/2024-05-gamma-staking/blob/703fd3604069489937037f20490ec8c492c0508e/StakingV2/src/Lock.sol#L455-L462

https://github.com/sherlock-audit/2024-05-gamma-staking/blob/703fd3604069489937037f20490ec8c492c0508e/StakingV2/src/Lock.sol#L538-L559

Tool used

Manual Review

Recommendation

Set the lockedWithMultiplier balance of the user to 0 after calculating the earnings in the _earned functions.

santipu03 commented 5 months ago

The process of withdrawing rewards and the process of withdrawing locked funds are independent of each other and work correctly. This issue is invalid because there's no impact, the user cannot double-claim rewards.