#42345 [SC-Critical] Theft of User Funds in executeRewardDistributionYeet During Vesting Period
Was this helpful?
Was this helpful?
Submitted on Mar 23rd 2025 at 06:16:35 UTC by @testnate for
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
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.
The issue occurs due to how accumulatedDeptRewardsYeet
calculates "accumulated rewards":
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.
executeRewardDistributionYeet
can 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.
This is a critical vulnerability that allows managers to steal or accidentally distribute users' funds:
Loss of User Funds: Users who have called startUnstake
can lose 100% of their tokens in the vesting period if a manager calls executeRewardDistributionYeet
.
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 unstake
after 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.
Add this contract in StakeV2.test.sol
Run forge test --use 0.8.20 -vvv --mt test_fundsLostDuringVestingPeriod