#42345 [SC-Critical] Theft of User Funds in executeRewardDistributionYeet During Vesting Period
Submitted on Mar 23rd 2025 at 06:16:35 UTC by @testnate for Audit Comp | Yeet
Report ID: #42345
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/StakeV2.sol
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
The executeRewardDistributionYeet function allows managers to distribute tokens that belong to users who have initiated the unstaking process but are still in the vesting period. This can lead to theft of users' funds, as demonstrated in the test case test_fundsLostDuringVestingPeriod. When users call startUnstake, their tokens are put into a vesting period but remain in the contract, where they're incorrectly counted as available rewards that managers can distribute.
Vulnerability Details
The issue occurs due to how accumulatedDeptRewardsYeet calculates "accumulated rewards":
function accumulatedDeptRewardsYeet() public view returns (uint256) {
return stakingToken.balanceOf(address(this)) - totalSupply;
}This calculation assumes that any tokens in the contract beyond the totalSupply are excess rewards. However, this is incorrect because it also includes tokens that are in vesting periods from users who have called startUnstake.
The vulnerability sequence:
When a user calls
startUnstake:
Their tokens are removed from balanceOf and totalSupply, but remain in the contract, marked only by a vestings struct.
executeRewardDistributionYeetcan then distribute these tokens:
A malicious or careless manager can distribute tokens that actually belong to users in the vesting period, causing them to permanently lose these funds.
Impact Details
This is a critical vulnerability that allows managers to steal or accidentally distribute users' funds:
Loss of User Funds: Users who have called
startUnstakecan lose 100% of their tokens in the vesting period if a manager callsexecuteRewardDistributionYeet.Scale of Impact: The issue affects all users who enter the vesting period through
startUnstake. Since the vesting period is 10 days long, this creates a large window where users' funds are at risk.No Recovery Mechanism: Once tokens are sent to the zapper, there's no way for users to recover them. When they attempt to call
unstakeafter the vesting period, the transaction fails due to insufficient token balance in the contract.
This is particularly problematic because users reasonably expect their tokens to be returned after the vesting period, but this vulnerability breaks this fundamental contract guarantee.
Proof of Concept
Proof of Concept
Add this contract in StakeV2.test.sol
Run forge test --use 0.8.20 -vvv --mt test_fundsLostDuringVestingPeriod
Was this helpful?