The StakingPool contract's withdrawal mechanism, specifically in the _withdrawLiquidity
function, may lead to user funds becoming inaccessible due to minimum deposit requirements in the OperatorVCS and CommunityVCS strategies. Late withdrawers may find a portion of their funds trapped in the contract, unable to be withdrawn even when theoretically available.
The vulnerability is present in the _withdrawLiquidity function of the StakingPool contract. This function attempts to withdraw funds from the two strategies (OperatorVCS and CommunityVCS) but does not account for their minimum deposit requirements, potentially leaving funds trapped.
The canWithdraw function in each strategy (OperatorVCS and CommunityVCS) likely returns the amount that can be withdrawn while maintaining the minimum required deposit. As the pool's liquidity decreases due to withdrawals, these strategies will approach their minimum deposit amounts. Once a strategy reaches its minimum, strategyCanWithdrawdraw will return zero, and no further withdrawals will be possible from that strategy.
This design can lead to a situation where funds equal to the sum of minimum deposits across both strategies become permanently locked in the contract, inaccessible to users.
The impact of this vulnerability is severe, with a moderate to high likelihood of occurrence:
Likelihood: Medium
As users withdraw over time, the likelihood of encountering this issue increases.
The problem becomes more pronounced as the total pool size decreases relative to the sum of minimum deposits required by OperatorVCS and CommunityVCS.
Severity: Medium
Late withdrawers may find a portion of their funds inaccessible.
This could lead to a loss of user trust and potential financial losses for affected users.
In extreme cases, a significant portion of the protocol's total value could become locked.
The combination of increasing likelihood over time and high severity makes this a critical issue to address.
Manual review
Consider the following scenario:
The StakingPool has 2 strategies: OperatorVCS and CommunityVCS, each with a minimum deposit of 100 tokens.
Initially, the pool has 1000 tokens, distributed as 500 tokens in each strategy.
Users withdraw 750 tokens, leaving 250 tokens in the pool.
The remaining 250 tokens are distributed as 100 in OperatorVCS and 150 in CommunityVCS.
A user attempts to withdraw 100 tokens.
In this scenario, the user cannot withdraw 100 tokens despite there being 250 tokens in the pool, because 200 tokens are locked as minimum deposits across the two strategies.
There doesn't seem to be a trivial fix for this.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.