The LSTRewardsSplitterController contract contains an unbounded loop in its checkUpkeep and performUpkeep functions. As the number of reward splitters increases, these functions may exceed the block gas limit or become too expensive to call. It is generally not a good practice to loop through an unbounded loop.
The checkUpKeep function retuns a bytes variable representing an array of booleans, whether to call performUpKeep on the given splitter or not. However the checkUpKeep function iterates through all of the splitters that are in the storage array accounts and mapping splitters. This number could grow to a number that is too big either hiting the block gas limit or causing the function performUpKeep to be too expensive to be called. On the other hand if any of the splitters's performUpKeep function reverts this will cause the whole function to revert, causing a DoS once again. For example if this condition is met - (uint256(newRewards) < controller.rewardThreshold()) the function will revert with InsufficientRewards().
Reward distributions could be delayed or fail entirely, affecting user returns and trust in the protocol.
The performUpKeep function can either hit the block gas limit or become too expensive to be called. This will make the function unusable.
Manual Review
Modify the checkUpkeep and performUpkeep functions to process a limited number of splitters per transaction. Implement a mechanism to track which splitters have been processed and continue from that point in subsequent calls.
Batch Processing: Implement a maximum batch size for processing splitters in a single transaction.
Tracking: Implement a more gas-efficient way to track which splitters need upkeep, such as using a bitmap or a separate queue for splitters needing processing.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.