Summary
LSTRewardsSplitter contract's constructor does not check if the total of the fees basis points is less than or equal to 10,000.
Vulnerability Details
The constructor of LSTRewardsSplitter contract has no checks for the total of fees basis points to be less than or equal 10,000.
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);
}
This would result in unintentionally high rewards splitting via LSTRewardsSplitter::splitRewards function, eventually decreasing the overall principalDeposits.
function _splitRewards(uint256 _rewardsAmount) private {
for (uint256 i = 0; i < fees.length; ++i) {
Fee memory fee = fees[i];
@> uint256 amount = (_rewardsAmount * fee.basisPoints) / 10000;
if (fee.receiver == address(lst)) {
IStakingPool(address(lst)).burn(amount);
} else {
lst.safeTransfer(fee.receiver, amount);
}
}
principalDeposits = lst.balanceOf(address(this));
emit RewardsSplit(_rewardsAmount);
}
Impact
Loss of principalDeposits due to over distribution (splitting) of the rewards.
Tools Used
Manual review
Recommendations
Add a _totalFeesBasisPoints check in the constructor
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]);
}
+ @> if (_totalFeesBasisPoints() > 10000) revert FeesExceedLimit();
_transferOwnership(_owner);
}