Liquid Staking

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

Delayed Effect of Reward Threshold Changes Causes Inconsistent Splitting Behavior

Details

The setRewardThreshold function in the LSTRewardsSplitterController contract is designed to update the minimum amount of rewards required before a split operation is performed. This threshold is meant to be used by individual LSTRewardsSplitter contracts.

The issue is that changing the rewardThreshold in the controller does not directly affect the behavior of existing LSTRewardsSplitter contracts. The splitters query the controller's threshold in their checkUpkeep function, but there's no mechanism to notify splitters of threshold changes or to trigger immediate checks.

Code Snippet

In LSTRewardsSplitterController:

function setRewardThreshold(uint256 _rewardThreshold) external onlyOwner {
rewardThreshold = _rewardThreshold;
}

In LSTRewardsSplitter:

function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
int256 newRewards = int256(lst.balanceOf(address(this))) - int256(principalDeposits);
if (newRewards < 0 || uint256(newRewards) >= controller.rewardThreshold())
return (true, bytes(""));
return (false, bytes(""));
}

Impact

  1. Delayed Effect: Changes to the reward threshold may not immediately affect the system's behavior.

  2. Inconsistent State: There could be a period where the controller's threshold and the actual splitting behavior are out of sync.

  3. Potential for Missed Splits: If the threshold is lowered, splitters won't immediately check if they now qualify for a split.

Scenario

  1. The system is running with a reward threshold of 1000 tokens.

  2. Several splitters have accumulated 800 tokens each.

  3. The owner decides to lower the threshold to 500 tokens and calls setRewardThreshold.

  4. Despite now being eligible for a split, the splitters won't perform one until their next checkUpkeep call.

  5. This delay could lead to larger-than-intended accumulations of rewards before splitting.

Fix

To address this issue, we need to implement a mechanism to trigger immediate checks on all splitters when the threshold changes.

In LSTRewardsSplitterController:

function setRewardThreshold(uint256 _rewardThreshold) external onlyOwner {
rewardThreshold = _rewardThreshold;
checkAllSplitters();
}
function checkAllSplitters() public {
bool[] memory splittersToCall = new bool[]();
bool overallUpkeepNeeded;
for (uint256 i = 0; i < accounts.length; ++i) {
(bool upkeepNeeded, ) = splitters[accounts[i]].checkUpkeep("");
splittersToCall[i] = upkeepNeeded;
if (upkeepNeeded) overallUpkeepNeeded = true;
}
if (overallUpkeepNeeded) {
performUpkeep(abi.encode(splittersToCall));
}
}

This fix ensures that when the reward threshold is changed, all splitters immediately check if they need to perform a split, maintaining system consistency and responsiveness to threshold changes.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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