Liquid Staking

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

Integer Overflow in `queueWithdrawal` Function

Summary

Unsafe typecasting vulnerability was identified in the queueWithdrawal function of the WithdrawalPool smart contract, where a uint256 value is cast to uint128 without appropriate checks. This could lead to integer overflow if the value exceeds the maximum representable value of uint128. This vulnerability could result in incorrect withdrawal amounts being processed, impacting users' funds.

Vulnerability Details

The vulnerability occurs in the following line of code within the queueWithdrawal function:

queuedWithdrawals.push(Withdrawal(uint128(sharesAmount), 0));

Here, the sharesAmount variable is of type uint256 but is cast to uint128. If the value of sharesAmount exceeds type(uint128).max (which is 2^128 - 1), an overflow will occur. This will lead to incorrect values being pushed into the queuedWithdrawals array. Since sharesAmount represents the number of shares being withdrawn, overflowing this value can cause users to withdraw fewer shares than intended, leading to financial loss.

For example, if the sharesAmount is 2^129, which in decimal is `680564733841876926926749214863536422912`, after the cast, it will be reduced to 0 because only the lower 128 bits are retained, effectively nullifying the withdrawal request for that user.

PoC

If you run the function from below, you will see that the return value will be 0:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
contract IntegerOverflowExample {
uint256 public largeNumber = 680564733841876926926749214863536422912; // 2^129
function overflowExample() public view returns (uint128) {
uint128 smallNumber = uint128(largeNumber);
return smallNumber;
}
}

Impact

  1. Financial Loss: If sharesAmount exceeds type(uint128).max, the overflow may result in incorrect withdrawal amounts, potentially leading to users receiving fewer tokens than they are entitled to.

  2. Data Integrity: The improper casting could corrupt the state of the queuedWithdrawals array, impacting subsequent operations dependent on the accuracy of these withdrawal amounts.

  3. Loss of Trust: Users may lose trust in the protocol if their withdrawal amounts are incorrectly processed, leading to potential loss of user confidence and platform credibility.

Tools Used

Manual Review

Recommendations

Introduce a Range Check: Before casting sharesAmount to uint128, ensure that its value is within the bounds of uint128. This can be achieved by adding a check like the following:

require(sharesAmount <= type(uint128).max, "Overflow: sharesAmount exceeds uint128 limit");

Use Safe Typecasting Libraries: Consider using libraries that provide safe casting operations, such as OpenZeppelin’s SafeCast library. This will automatically check for overflows and revert the transaction if an unsafe cast is attempted.

import "@openzeppelin/contracts/utils/math/SafeCast.sol";
uint128 safeSharesAmount = SafeCast.toUint128(sharesAmount);
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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