The LSTRewardsSplitterController::performUpkeep contains the logic to call performUpkeep on any LSTRewardsSplitter that was flagged as requiring upkeep in LSTRewardsSplitterController::checkUpkeep splitting new rewards between fee receivers.
The LSTRewardsSplitter::performUpkeep is missing an access control so can be called anytime by anyone leading to a race condition when called concurrently with the LSTRewardsSplitterController::performUpkeep (on the same LSTRewardsSplitter flagged as requiring upkeep in the list). The race condition occurs because both functions independently calculate and split rewards based on the balance of the LSTRewardsSplitter contract.
When performUpkeep is called in both contracts on the same LSTRewardsSplitter at the same time, each function calculates rewards independently and either function proceeds to split rewards before the other completes. This results in duplicate reward splitting and inconsistent state updates.
Likelihood: very low (execution on the same splitter must be at the same time)
Impact: medium/high (rewards on fee receiver are duplicated)
Manual review
Add onlyController modifier in the LSTRewardsSplitter::performUpkeep.
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.