Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: high
Invalid

Flaw in PriorityPool Deposit Logic Prevents LST Allocation for Direct Deposits

Summary

In the PriorityPool::_deposit function, asset tokens directly deposited into the staking pool do not receive LST allocations, nor is the corresponding user data recorded for future LST distributions, resulting in users being unable to obtain the LST associated with these asset tokens.

Vulnerability Details

When users deposit asset tokens into the PriorityPool, the system first checks if there are any queued withdrawal requests in the WithdrawalPool. If there are, these asset tokens will be transferred to the WithdrawalPool, and users will receive the corresponding liquidity staking tokens. If there are remaining tokens and the staking pool has available space, the system will call the StakingPool::deposit function to stake the assets. However, the tokens directly deposited into the staking pool do not receive the corresponding liquidity staking tokens, and the relevant account information is not updated,LST distributions rely on this account data through a Merkle tree, which means these tokens will be unable to participate in future LST distributions.

function _deposit(
address _account,
uint256 _amount,
bool _shouldQueue,
bytes[] memory _data
) internal {
if (poolStatus != PoolStatus.OPEN) revert DepositsDisabled();
uint256 toDeposit = _amount;
if (totalQueued == 0) {
uint256 queuedWithdrawals = withdrawalPool.getTotalQueuedWithdrawals();
if (queuedWithdrawals != 0) {
uint256 toDepositIntoQueue = toDeposit <= queuedWithdrawals
? toDeposit
: queuedWithdrawals;
withdrawalPool.deposit(toDepositIntoQueue);
toDeposit -= toDepositIntoQueue;
IERC20Upgradeable(address(stakingPool)).safeTransfer(_account, toDepositIntoQueue);
}
if (toDeposit != 0) {
uint256 canDeposit = stakingPool.canDeposit();
if (canDeposit != 0) {
uint256 toDepositIntoPool = toDeposit <= canDeposit ? toDeposit : canDeposit;
@> stakingPool.deposit(_account, toDepositIntoPool, _data);
toDeposit -= toDepositIntoPool;
}
}
}
if (toDeposit != 0) {
if (_shouldQueue) {
_requireNotPaused();
if (accountIndexes[_account] == 0) {
accounts.push(_account);
accountIndexes[_account] = accounts.length - 1;
}
accountQueuedTokens[_account] += toDeposit;
totalQueued += toDeposit;
} else {
token.safeTransfer(_account, toDeposit);
}
}
emit Deposit(_account, _amount - toDeposit, _shouldQueue ? toDeposit : 0);
}

Impact

This flaw may cause a portion of the user's funds to be locked and unrecoverable.

Tools Used

Manual Audit.

Recommendations

Update User Data on Direct Deposits: Modify the PriorityPool::_deposit function to ensure that when asset tokens are directly deposited into the staking pool, the corresponding user data is recorded. This includes updating the PriorityPool::accounts array, PriorityPool::accountIndexes, PriorityPool::depositsSinceLastUpdate, PriorityPool::sharesSinceLastUpdateand any relevant tracking variables similarly to how it is done for queued deposits. This will allow these deposits to participate in future LST distributions. Alternatively, the liquidity from these direct deposits could be sent to users, but this may disrupt the current LST allocation mechanism based on the Merkle tree.

Updates

Lead Judging Commences

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

siisivan Submitter
11 months ago
inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.