Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: high
Invalid

FeesLimit can be bypassed in LSTRewardsSplitterController:: addSplitter

Summary

In the LSTRewardsSplitter contract, it can be observed in the addFee and updateFee functions that there is a FeeLimit, and these functions have a check to make sure that _totalFeesBasisPoints is not greater than the hardcoded value 10000. This check was not done in the LSTRewardsSplitter constructor, where the initial Fee receivers were added.

Vulnerability Details

The FeeLimit for the LSTRewardsSplitter contract, which was hardcoded 10000can be bypassed during the creation of the LSTRewardsSplitter contract. The initial Fee receivers are added during the contract creation through the constructor but there is no check in the constructor to make sure that the _totalFeesBasisPoints is not greater than 10000.

https://github.com/Cyfrin/2024-09-stakelink/blob/main/contracts/core/lstRewardsSplitter/LSTRewardsSplitter.sol#L50

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);
// No check if fees limit is exceeded
}
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);
}

Impact

  1. A fee receiver could potentially receive a percentage greater than 100%, which could divert more funds than intended.

  2. It undermines the logic of the contract, leading to a potential exploit where all funds could be allocated to a single receiver or distributed disproportionately, affecting the fairness of the reward-sharing mechanism.

Tools Used

Manual Review

Recommendations

There should be a validation in the LSTRewardsSplitter contract contructor that ensures the sum of _totalFeesBasisPoints across all fee receivers does not exceed the limit of 10000 basis points.

constructor(address _lst, Fee[] memory _fees, address _owner) {
controller = ILSTRewardsSplitterController(msg.sender);
lst = IERC677(_lst);
+ uint256 totalFees;
for (uint256 i = 0; i < _fees.length; ++i) {
fees.push(_fees[i]);
+ totalFees += _fees[i].basisPoints;
}
+ if (totalFees > 10000) revert FeesExceedLimit();
_transferOwnership(_owner);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.