The LSTRewardsSplitterController::removeSplitter is designed to remove a splitter contract from the array of splitters. The function executes by splitting any available rewards and withdraws any balances from the splitter contract before removing the splitter from the array of splitters.
However, this function will always revert for any splitter contract that has some funds in it, breaking the functionality of the protocol.
The LSTRewardsSplitterController::removeSplitter function reverts for any splitter contract with a positive balance because during function execution, the balance of the splitter contract is cached as balance, the principal deposits in the splitter contract is cached as principalDeposits.
The function then checks if balance is zero or not. Where the balance is zero, the function works fine.
The problem lies where the balance is greater than zero. This is because, the function checks if balance != principalDeposits. Where balance is not equal to principalDeposits, it means there are rewards for distribution and the splitter will distribute the rewards. Now, after distributing rewards, the protocol attempts to withdraw the cached balance from the splitter contract whereas, the tokens remaining in the splitter contract is now less than the cached balance. Since the protocol attempts to withdraw more tokens from the splittr contract than the current balance, it triggers an arithmetic overflow or underflow causing the call to revert.
The code snippet is shown below and can be further confirmed using the following github link https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/lstRewardsSplitter/LSTRewardsSplitterController.sol#L130-L153
Since the LSTRewardsSplitterController::removeSplitter reverts whenever the splitter contract has some tokens in it, the protocol fails to remove any splitter contract that has positive balance even if it is desirable to do so. This affects the protocol's functionality.
Manual Review and Hardhat
Proof of Concept:
Add a splitter to the protocol
Send some tokens to the splitter so that the splitter has a positive balance
Attempt to remove the splitter from the array of splitters on the protocol. The execution will fail due to arithmetic underflow or overflow causing the call to revert
Run: yarn test
Output:
The test reverts as expected. To confirm that the test reverts due to arithmetic overflow or underflow, we can slightly adjust the code snippet for the test above to see the error message. Consider modifying the code snippet as below:
Run: yarn test
Output:
The above output confirms that the call reverts due to arithmetic overflow or underflow.
Consider modifying the LSTRewardsSplitterController::removeSplitter function such that it withdraws the current balance of the splitter contract after splitting rewards rather than attempting to withdraw an amount that corresponds to the splitter balance cached before splitting rewards.
With this adjustment, the LSTRewardsSplitterController::removeSplitter function will execute as expected, enhancing the protocol's functionality.
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.