The StakingPool contract allows the accumulation of unused deposits up to a configurable limit (unusedDepositLimit). This can result in idle tokens in the contract that don’t generate yield, potentially reducing overall returns for users.
The deposit function in the StakingPool contract includes the following check:
This check allows deposits to succeed as long as the unused balance doesn’t exceed the unusedDepositLimit. The limit is configurable by the contract owner:
If unusedDepositLimit is set to zero, all deposits that increase the contract’s balance will revert. If set to a non-zero value, deposits can leave tokens idle in the contract up to this limit.
The core of the issue lies in the _depositLiquidity function:
The first strategy reports it can accept all tokens (strategyCanDeposit >= toDeposit).
The function attempts to deposit all tokens to this strategy.
The loop immediately breaks, assuming all funds are invested.
In reality, if the strategy doesn’t accept the full amount, the excess tokens are returned to the staking pool.
These returned funds remain idle, as no further strategies are tried.
Reduced Yields: Users’ deposits may not be fully invested, leading to lower overall returns.
Inefficient Capital Utilization: A portion of the deposited funds remains idle and unproductive.
Misleading User Expectations: Users may assume their entire deposit is being invested immediately, but some of their funds may remain idle in the pool.
Accumulated Idle Funds: Over time, a significant amount of idle tokens could accumulate in the contract.
Opportunity Cost: The yield that could have been earned on these idle tokens represents a real loss for users.
Cause:
The design prioritizes depositing into the first strategy, even if it can’t accept the full amount.
The unusedDepositLimit mechanism allows some unused deposits to remain idle in the contract.
Likelihood:
High. This issue is likely to occur frequently, especially if:
The first strategy often can’t accept full deposits.
The unusedDepositLimit is set to a non-zero value.
There is high deposit activity in the system.
Owner has set unusedDepositLimit to 1000 tokens.
User A deposits 1000 tokens, but the first strategy only accepts 800, and the loop breaks, assuming all tokens are invested.
200 tokens are returned to the staking pool and remain idle in the contract.
User B deposits 900 tokens; the first strategy accepts 700.
Now, 400 tokens are idle and not earning yield.
This process continues until idle tokens reach the unusedDepositLimit.
There are several potential improvements that could enhance the investment strategy process:
Modify _depositLiquidity() to continue attempting subsequent strategies if the first one doesn’t accept the full amount.
Implement a function to periodically invest idle tokens across all strategies.
Provide users with clear information about what portion of their deposit is actively invested versus idle.
Allow for dynamic adjustment of strategy priority based on capacity and performance.
Consider implementing a low-risk, liquid strategy to temporarily utilize idle funds.
Allow users to specify preferences for deposit behavior (e.g., fully invest or return unused funds).
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.