Liquid Staking

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

Inaccurate Withdrawal Tracking

Summary

Inaccurate Withdrawal Tracking

Vulnerability Details

/**
* @notice Executes a group of fully and/or partially finalized withdrawals owned by the sender
* @param _withdrawalIds list of withdrawal ids to execute
* @param _batchIds list of batch ids corresponding to withdrawal ids
*/
function withdraw(uint256[] calldata _withdrawalIds, uint256[] calldata _batchIds) external {
address owner = msg.sender;
uint256 amountToWithdraw;
for (uint256 i = 0; i < _withdrawalIds.length; ++i) {
uint256 withdrawalId = _withdrawalIds[i];
Withdrawal memory withdrawal = queuedWithdrawals[_withdrawalIds[i]];
uint256 batchId = _batchIds[i];
WithdrawalBatch memory batch = withdrawalBatches[batchId];
if (withdrawalOwners[withdrawalId] != owner) revert SenderNotAuthorized();
if (
batchId != 0 && withdrawalId <= withdrawalBatches[batchId - 1].indexOfLastWithdrawal
) revert InvalidWithdrawalId();
if (
batchId != 0 &&
withdrawalId > batch.indexOfLastWithdrawal &&
withdrawal.partiallyWithdrawableAmount == 0
) revert InvalidWithdrawalId();
if (withdrawalId <= batch.indexOfLastWithdrawal) {
amountToWithdraw +=
withdrawal.partiallyWithdrawableAmount +
(uint256(batch.stakePerShares) * uint256(withdrawal.sharesRemaining)) /
1e18;
delete queuedWithdrawals[withdrawalId];
delete withdrawalOwners[withdrawalId];
} else {
amountToWithdraw += withdrawal.partiallyWithdrawableAmount;
queuedWithdrawals[withdrawalId].partiallyWithdrawableAmount = 0;
}
}
token.safeTransfer(owner, amountToWithdraw);
emit Withdraw(owner, amountToWithdraw);
}

The withdraw function processes each withdrawal ID and batch ID without adequately handling partial withdrawals. Specifically, it does not update the sharesRemaining or partiallyWithdrawableAmount correctly when a withdrawal is partially fulfilled.

Impact

Users may not receive the correct amount of LSTs based on their shares, leading to over- or under-claiming.Incorrect updates can disrupt the FIFO order of withdrawals, potentially allowing newer withdrawals to be processed before older ones.

Tools Used

Manual Review

Recommendations

process both full withdrawal and partial withdrawal

Updates

Lead Judging Commences

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.