Summary
The __totalFeesBasisPoints of the LSTRewardsSplitter must not be allowed to surpass 10_000, however this is not enforced on construction.
Vulnerability Details
Fees for an LSTRewardSplitter may never exceed 10_000 in total:
* @notice Sdds a new fee
* @param _receiver receiver of fee
* @param _feeBasisPoints fee in basis points
**/
function addFee(address _receiver, uint256 _feeBasisPoints) external onlyOwner {
fees.push(Fee(_receiver, _feeBasisPoints));
if (_totalFeesBasisPoints() > 10000) revert FeesExceedLimit();
}
However, this limit isn't forced upon construction:
constructor(address _lst, Fee[] memory _fees, address _owner) {
controller = ILSTRewardsSplitterController(msg.sender);
lst = IERC677(_lst);
for (uint256 i = 0; i < _fees.length; ++i) {
fees.push(_fees[i]);
}
_transferOwnership(_owner);
}
Neither is this enforced by the LSTRewardsSplitterController:
* @notice Deploys a new splitter
* @param _account address of account to deploy splitter for
* @param _fees list of splitter fees
*/
function addSplitter(
address _account,
LSTRewardsSplitter.Fee[] memory _fees
) external onlyOwner {
if (address(splitters[_account]) != address(0)) revert SplitterAlreadyExists();
address splitter = address(new LSTRewardsSplitter(lst, _fees, owner()));
splitters[_account] = ILSTRewardsSplitter(splitter);
accounts.push(_account);
IERC677(lst).safeApprove(splitter, type(uint256).max);
}
Consequently, the invariant is not respected.
Impact
Broken composablity of LstRewardsSplitter resulting in potentially undue excess fees.
Tools Used
Manual Review
Recommendations
Instead of manually assigning the fees, use addFee in the constructor to implictly enforce the upper bound on fees:
constructor(address _lst, Fee[] memory _fees, address _owner) {
controller = ILSTRewardsSplitterController(msg.sender);
lst = IERC677(_lst);
for (uint256 i = 0; i < _fees.length; ++i) {
- fees.push(_fees[i]);
+ addFee(_fees[i].reciever, _fees[i].basisPoints);
}
_transferOwnership(_owner);
}