#42382 [SC-Critical] Calling `StakeV2::executeRewardDistributionYeet` by manager during an ongoing unstaking period for stakers can result in them being unable to unstake permanently
Submitted on Mar 23rd 2025 at 13:15:22 UTC by @hustling0x for Audit Comp | Yeet
Report ID: #42382
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol
Impacts:
Permanent freezing of funds
Description
Brief/Intro
The StakeV2::executeRewardDistributionYeet method uses StakeV2::accumulatedDeptRewardsYeet to determine the amount of $YEET to zap in and distribute as excess rewards. However, the StakeV2::accumulatedDeptRewardsYeet method falsely returns accumulated rewards in $YEET tokens when there are users who have requested to unstake via StakeV2::startUnstake. This means that every time StakeV2::executeRewardDistributionYeet is called by a manager, the tokens intended to be unstaked by the users will be sent to the Zapper and distributed as excess rewards, resulting in a permanent freeze and permanent inability for users to withdraw their staked $YEET positions.
Vulnerability Details
When a user calls StakeV2::startUnstake, the totalSupply of staked tokens ($YEET) in the contract is reduced by the amount requested for unstake. This way, the calculation in StakeV2::accumulatedDeptRewardsYeet will return a false result, not taking into account the amounts pending to be unstaked.
For example:
A yeetard stakes 1000 $YEET ->
totalSupply= 1000 $YEET,accumulatedDeptRewardsYeetreturns 0;He calls
StakeV2::startUnstaketo request unstake ->totalSupply= 0 $YEET, but nowaccumulatedDeptRewardsYeetreturns 1000 $YEET, because of the calculationstakingToken.balanceOf(address(this)) - totalSupply;
This means at any time there are pending unstaking periods running for users and the manager calls StakeV2::executeRewardDistributionYeet, users' tokens will be zapped and distributed as excess rewards, and they will not be able to unstake them via StakeV2::unstake or StakeV2::rageQuit.
Impact Details
Although the method StakeV2::executeRewardDistributionYeet is only callable by a manager, calling it while there are active unstaking periods ongoing will result in DoS and permanent freezing of users' staked funds.
Recommended Mitigation
The proposed solution is to keep track of the total pending unstakes for the contract and deduct them in the calculation in StakeV2::accumulatedDeptRewardsYeet.
The totalPendingUnstakeAmount state should be updated when StakeV2::startUnstake is called and when the user actually unstakes either via StakeV2::unstake or StakeV2::rageQuit.
References
https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L148
https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L158
https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L255
Proof of Concept
Proof of Concept
Was this helpful?