#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,accumulatedDeptRewardsYeet
returns 0;He calls
StakeV2::startUnstake
to request unstake ->totalSupply
= 0 $YEET, but nowaccumulatedDeptRewardsYeet
returns 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?