#42443 [SC-Critical] Vested `$YEET` are susceptible of being impossible to unstake
Submitted on Mar 23rd 2025 at 23:28:54 UTC by @greed for Audit Comp | Yeet
Report ID: #42443
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol
Impacts:
Temporary freezing of funds for at least 24 hours
Description
Summary
Users have the ability to stake $YEET
tokens in the StakeV2.sol
contract in order to get rewards.
At any point, a user is allowed to unstake his tokens which will be submitted to a vesting period of 10 days. The vested amount of tokens will be claimable and effectively unstaked after this period has passed.
Contract managers can execute the distribution of $YEET
rewards which will distribute the excess of tokens across all stakers.
This excess is wrongly calculated and includes the vested tokens users are trying to unstake.
Vulnerability details
The number of tokens users have staked in the contract is accounted in the totalSupply
variable. This number is increased everytime a user stakes and everytime a user starts the unstake process.
https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L240https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L255
The function involved when calculating the rewards to distribute subtracts the $YEET
token balance of the contract with the totalSupply
.
https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol#L149
Thus, the resulting amount of rewards fail to account for the vested amount of tokens waiting to be unstaked.
This means when the vesting period has ended, a user might not be able to claim his tokens because the contract does not have enough liquidity.
Impact
Users might be prevented from withdrawing their tokens after unstaking them.
Proof of Concept
Proof of concept
Alice stakes 800 tokens:
totalSupply == 800
The Yeet game is being played and 1000 tokens are accrued as rewards:
stakingToken.balanceOf(address(this)) == 1800
Alice wants to unstake her 800 tokens so she starts the vesting period to claim them 10 days later:
totalSupply == 800 - 800 == 0
Manager distributes the maximum amount of rewards possible:
stakingToken.balanceOf(address(this)) - totalSupply
meaning1800 - 0 == 1800
When Alice attempts to unstake her 800 tokens, the transaction will fail because the contract
Recommendation
Maintain a storage variable
vestedTokens
that accounts for the vested amount of$YEET
and increases everytime a userstartUnstake()
and decreases when a userunstake()
.Modify the
accumulatedDeptRewardsYeet()
to account for the vested tokens.
Was this helpful?