Liquid Staking

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

Weak Constraint Enforcement in `LSTRewardsSplitter::performUpkeep` Allows Griefing via `splitRewards`

Summary

The LSTRewardsSplitter::performUpkeep function correctly enforces a constraint that prevents users from calling _splitRewards() unless the newRewards value is greater than or equal to the controller.rewardThreshold(). However, this same restriction is not enforced in the LSTRewardsSplitter::splitRewards function, which can be used to achieve the same outcome. The lack of consistent enforcement allows a griefer to split rewards prematurely, potentially causing the protocol to miss out on any benefits of letting rewards build up.

Vulnerability Details

The performUpkeep function includes a condition that ensures _splitRewards() is only called when newRewards is greater than or equal to the rewardThreshold():

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));
}
}

However, the splitRewards function does not enforce this same threshold and allows rewards to be split as long as newRewards is not zero:

function splitRewards() external {
int256 newRewards = int256(lst.balanceOf(address(this))) - int256(principalDeposits);
if (newRewards < 0) {
principalDeposits -= uint256(-1 * newRewards);
} else if (newRewards == 0) {
revert InsufficientRewards();
} else {
_splitRewards(uint256(newRewards));
}
}

The lack of a threshold check in splitRewards creates a vulnerability where an attacker or griefer can call the function prematurely, splitting rewards before they accumulate to a sufficient level. This prevents the protocol from achieving any potential advantages from allowing rewards to build up, such as minimizing gas costs for reward distribution or achieving higher reward thresholds.

Impact

A malicious user can grief the system by calling splitRewards before rewards reach the intended rewardThreshold, forcing premature reward distributions..

Tools Used

Manual

Recommendations

Enforce Consistent Constraints: Apply the same rewardThreshold() check in the splitRewards function that is present in performUpkeep. This will ensure that rewards are only split when they reach the required threshold, preventing premature distributions.

Updates

Lead Judging Commences

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