Liquid Staking

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

`LSTRewardsSplitter::constructor()` missing `fees` validation

Summary

_totalFeesBasisPoints() > 10000 check is missing in the LSTRewardsSplitter:constructor() after fees initialization. _totalFeesBasisPoints() checks that the total sum of fees in basis points not exceed 10000 (100%). Without this check, fees can be initialized with incorrect data.

Vulnerability Details

The LSTRewardsSplitter:_splitRewards() uses fees to determine what share of the reward should be sent to the specified receivers. If the total sum of fees in basis points exceeds 10000 (100%) then LSTRewardsSplitter:_splitRewards() will withdraw from the principal deposits.

Impact

User may lose principal deposit.

Proof of Code

Add this test to lst-rewards-splitter.test.ts:

async function DeployFixture2() {
const { accounts, signers } = await getAccounts()
const token = (await deploy('LSTMock', ['Token', 'TKN', 100000000])) as LSTMock
await setupToken(token, accounts)
const controller = (await deploy('LSTRewardsSplitterController', [
token.target,
toEther(100),
])) as LSTRewardsSplitterController
await controller.addSplitter(accounts[0], [
{ receiver: accounts[5], basisPoints: 10000 },
{ receiver: accounts[6], basisPoints: 10000 },
])
const splitter = await ethers.getContractAt(
'LSTRewardsSplitter',
await controller.splitters(accounts[0])
)
return { signers, accounts, token, controller, splitter }
}
it('principalDeposits() returns 0 after _splitRewards()', async () => {
const { accounts, controller, token, splitter } = await loadFixture(DeployFixture2)
await token.transferAndCall(controller.target, toEther(100), '0x')
await token.transfer(splitter.target, toEther(100))
await splitter.splitRewards()
assert.equal(fromEther(await splitter.principalDeposits()), 0)
assert.equal(fromEther(await token.balanceOf(splitter.target)), 0)
assert.equal(fromEther(await token.balanceOf(accounts[5])), 100)
assert.equal(fromEther(await token.balanceOf(accounts[6])), 100)
})

Tools Used

Manual review.

Recommendations

Add _totalFeesBasisPoints() > 10000 in the LSTRewardsSplitter: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);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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