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

9 stars 7 forks source link

valentin2304 - exiting early will cause accumulated rewards for staker to be lost #299

Closed sherlock-admin2 closed 5 months ago

sherlock-admin2 commented 6 months ago

valentin2304

high

exiting early will cause accumulated rewards for staker to be lost

Summary

exiting early will cause accumulated rewards for staker to be lost, because after user calls earlyExitById his bal.lockWithMultiplier will be set to 0 causing his rewards in earned to get multiplied by 0 causing loss of funds for the user

Vulnerability Detail

function earlyExitById(uint256 lockId) external whenNotPaused {
        if (isEarlyExitDisabled) {
            revert EarlyExitDisabled();
        }
        _updateReward(msg.sender);

        LockedBalance memory lock = locklist.getLockById(msg.sender, lockId);

        if (lock.unlockTime != 0)
            revert InvalidLockId();
        uint256 coolDownSecs = calcRemainUnlockPeriod(lock);
        lock.unlockTime = block.timestamp + coolDownSecs;
        uint256 penaltyAmount = calcPenaltyAmount(lock);
        locklist.removeFromList(msg.sender, lockId);
        Balances storage bal = balances[msg.sender];
        lockedSupplyWithMultiplier -= lock.amount * lock.multiplier;
        lockedSupply -= lock.amount;
        bal.locked -= lock.amount;
        bal.lockedWithMultiplier -= lock.amount * lock.multiplier; //here balance for user gets set back to 0

        _updateRewardDebt(msg.sender);

        if (lock.amount > penaltyAmount) {
            IERC20(stakingToken).safeTransfer(msg.sender, lock.amount - penaltyAmount);
            IERC20(stakingToken).safeTransfer(treasury, penaltyAmount);
            emit EarlyExitById(lockId, msg.sender, lock.amount - penaltyAmount, penaltyAmount);
        } else {
            IERC20(stakingToken).safeTransfer(treasury, lock.amount);
        emit EarlyExitById(lockId, msg.sender, 0, penaltyAmount);
        }
    }

After user calls earlyExitById his bal.lockWithMultiplier will be set to 0 causing his rewards in earned to get multiplied by 0 making unable for user to get his rewards

    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.
    }

Impact

High

Code Snippet

https://github.com/sherlock-audit/2024-05-gamma-staking/blob/main/StakingV2/src/Lock.sol#L313

Tool used

Manual Review

Recommendation

Implement a check if the staker has called exitEarlyById or not

santipu03 commented 5 months ago

This issue is invalid because the rewards are not lost when a user withdraws, they're stored in the rewards mapping.