#41911 [SC-Critical] Unstake amount can be zapped before user withdrawal
Submitted on Mar 19th 2025 at 10:06:16 UTC by @Ragnarok for Audit Comp | Yeet
Report ID: #41911
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 contract has a flaw in the startUnstake function that can lead to a permanent loss of user funds. When users initiate an unstake request, the contract’s totalSupply decreases, but its stakingToken balance remains unchanged. This discrepancy causes the contract’s accumulatedDeptRewardsYeet to increase, creating a potential risk where a manager can use these funds before users can withdraw them.
Vulnerability Details
When a user initiates an unstake, they must first call the StakeV2::startUnstake function. However, this function only decreases totalSupply without affecting the contract’s stakingToken balance.
StakeV2::startUnstake function:
function startUnstake(uint256 unStakeAmount) external {
...
// @note totalSupply decreases, but the YEET balance of this contract does not change
// @note As a consequence, accumulatedDeptRewardsYeet increases (balance - totalSupply)
// @audit Users lose funds if the manager calls executeRewardDistributionYeet.
totalSupply -= unStakeAmount;
...
}Because of this, the StakeV2::accumulatedDeptRewardsYeet() will increase by the same amount the user intends to unstake. The unstaked amount remains locked in the contract, users are allowed to withdraw all after 10 days.
However, what if, before the lock period ends, the manager calls StakeV2::executeRewardDistributionYeet, utilizing all accumulatedDeptRewardsYeet() funds. Then the unstake amount is zapped into the Zapper contract, permanently removing it from StakeV2. When the user attempts to withdraw their unstaked tokens after the waiting period, the contract no longer has the funds, leading to irrecoverable user losses.
Impact Details
The
StakeV2contract will permanently lose funds allocated for unstaking.Some users may be unable to withdraw their full staked amount due to missing funds.
Proof of Concept
Proof of Concept
Put the following code into the test/StakeV2.test.sol file and run forge test --mt test_unableToUnstake.
Was this helpful?