Liquid Staking

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

Principal Deposits Can Become Negative in LSTRewardsSplitter

Summary

When the newRewards variable, calculated as the difference between the contract's LST token balance and principalDeposits, becomes negative.

Vulnerability Details

This line attempts to subtract the absolute value of newRewards from principalDeposits using an unsigned integer (uint256), which can lead to an underflow if the absolute value of newRewards is greater than principalDeposits. https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/lstRewardsSplitter/LSTRewardsSplitter.sol#L101-L110

function performUpkeep(bytes calldata) external {
int256 newRewards = int256(lst.balanceOf(address(this))) - int256(principalDeposits);
if (newRewards < 0) {
principalDeposits -= uint256(-1 * newRewards);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} else if (uint256(newRewards) < controller.rewardThreshold()) {
revert InsufficientRewards();
} else {
_splitRewards(uint256(newRewards));
}
}

When the newRewards variable calculated as the difference between the contract's LST token balance and principalDeposits becomes negative. In this case, the contract attempts to subtract the absolute value of newRewards from principalDeposits using an unsigned integer (uint256). However, if the absolute value of newRewards is greater than principalDeposits, an underflow occurs, resulting in principalDeposits becoming a large positive value instead of a negative value.

Steps

  1. The vulnerability can be triggered by calling the performUpkeep function when the contract's LST token balance is less than principalDeposits.

  2. The reason for this vulnerability is the incorrect handling of negative newRewards values in the performUpkeep function. The subtraction of the absolute value of newRewards from principalDeposits is performed using an unsigned integer (uint256), which can lead to an underflow if the absolute value of newRewards is greater than principalDeposits.

Using an unsigned integer (uint256) for the subtraction operation in the performUpkeep function is a mistake, as it does not properly handle negative values and can lead to an underflow.

Scenario:

  1. The LSTRewardsSplitter contract is deployed with an initial principalDeposits value of 100.

  2. A user calls the withdraw function to withdraw 50 tokens, reducing principalDeposits to 50.

  3. The contract's LST token balance is manipulated externally, causing it to become less than principalDeposits. For example, the balance becomes 30.

  4. Another user calls the performUpkeep function.

  5. Inside performUpkeep, newRewards is calculated as 30 - 50 = -20.

  6. The contract attempts to subtract the absolute value of newRewards (20) from principalDeposits (50) using uint256, resulting in an underflow.

  7. principalDeposits becomes a large positive value instead of the expected negative value, violating the contract's invariant.

Impact

When newRewards is negative, the contract attempts to subtract the absolute value of newRewards from principalDeposits. However, this subtraction is performed using an unsigned integer (uint256), which can lead to an underflow if the absolute value of newRewards is greater than principalDeposits.

Tools Used

Manual Review

Recommendations

The subtraction operation should be performed using signed integers to handle negative values correctly.

function performUpkeep(bytes calldata) external {
int256 newRewards = int256(lst.balanceOf(address(this))) - int256(principalDeposits);
if (newRewards < 0) {
- principalDeposits -= uint256(-1 * newRewards);
+ principalDeposits = uint256(int256(principalDeposits) + newRewards);
} else if (uint256(newRewards) < controller.rewardThreshold()) {
revert InsufficientRewards();
} else {
_splitRewards(uint256(newRewards));
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 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.