Liquid Staking

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

Withdrawing From An `OperatorStakingPool` Does Not Send Tokens

Summary

No tokens are received when withdrawing from an OperatorStakingPool.

Vulnerability Details

Authorized operators may deposit into the OperatorStakingPool by transferring LST tokens:

/**
* @notice ERC677 implementation to receive deposits
* @param _sender address of sender
* @param _value amount of tokens to deposit
**/
function onTokenTransfer(address _sender, uint256 _value, bytes calldata) external {
if (msg.sender != address(lst)) revert InvalidToken();
if (!isOperator(_sender)) revert SenderNotAuthorized();
if (getOperatorStaked(_sender) + _value > depositLimit) revert ExceedsDepositLimit();
uint256 sharesAmount = lst.getSharesByStake(_value);
shareBalances[_sender] += sharesAmount;
totalShares += sharesAmount;
emit Deposit(_sender, _value, sharesAmount);
}

However, when authorized operators intend to withdraw from the pool, the tokens are not returned:

function withdraw(uint256 _amount) external {
if (!isOperator(msg.sender)) revert SenderNotAuthorized();
@> _withdraw(msg.sender, _amount);
}

https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/linkStaking/OperatorStakingPool.sol#L132C5-L135C6

function _withdraw(address _operator, uint256 _amount) private {
@> uint256 sharesAmount = lst.getSharesByStake(_amount);
@> shareBalances[_operator] -= sharesAmount;
@> totalShares -= sharesAmount;
@> emit Withdraw(_operator, _amount, sharesAmount);
}

https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/linkStaking/OperatorStakingPool.sol#L199C5-L205C6

As demonstrated, at no point is underlying LST returned to the rightful operator.

Impact

Stuck funds, irrecoverable loss of stake.

Tools Used

Manual Review

Recommendations

Transfer the owed tokens to a specified recipient address at the end of the _withdraw function.

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`OperatorStakingPool::_withdraw()` function doesn't transfer the tokens

Support

FAQs

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