Liquid Staking

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

`LSTRewardsSplitterController:performUpkeep` will be reverted due to front running

Summary

The perform upkeep tries to distubute the rewards to all the fee receivers that return true from the checkUpKeep call, but the performUpKeep can also be called directly on the specific splitter, which will lead to reverts, and the performUpKeep cannot be succeeded.

Vulnerability Details

To split the rewards, first we need to confirm that the rewards can be split; for this we call checkUpkeep.

function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
bool[] memory splittersToCall = new bool[]();
bool overallUpkeepNeeded;
for (uint256 i = 0; i < splittersToCall.length; ++i) {
(bool upkeepNeeded, ) = splitters[accounts[i]].checkUpkeep("");
splittersToCall[i] = upkeepNeeded;
if (upkeepNeeded) overallUpkeepNeeded = true;
}
return (overallUpkeepNeeded, abi.encode(splittersToCall));
}

if it returns true then we will call the performUpKeep function, which will call LSTRewardsSplitter:performUpKeep and split the rewards in fee receiver.

The PerformUpkeep function of LSTRewardsSplitter checks that the total lst balance and pricnipal deposit is more than the rewards threshold, then calls the _splitRewards function, which distributes the fee to the fee receiver and updates the principalDeposits=lst.balanceOf(address(this)).

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

POC:

  1. The keeper calls the checkupKeep and receives true for the overall split and with the 4 splitter.

  2. Keeper submits the transaction for performUpKeep for these 4 splitters.

  3. Bob monitors the transaction and frontruns the Keeper transaction and performUpkeep on one of the splitters.

  4. When the execution node picks the Keeper transaction, it will be reverted with this message: InsufficientRewards.

Impact

The keeper transaction will be frontrun by malicious users and will result in DoS for keeper.

Tools Used

Manual Review

Recommendations

Remove the revert condition and simply return it, no rewards to split.

Updates

Lead Judging Commences

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

Appeal created

0xaman Submitter
7 months ago
inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 7 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.