Liquid Staking

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

Protocol Fails to Distribute LST Rewards to Operators

Summary

In the OperatorVCS::updateDeposits function, rewards for operators are intended to be distributed via the StakingPool contract. However, the StakingPool::_updateStrategyRewards function mistakenly distributes all Liquid Staking Tokens (LST) to fee receivers, completely neglecting the allocation of rewards to operators. This oversight results in operators not receiving their rightful share of rewards.

Vulnerability Details

When OperatorVCS::updateDeposits is called by the StakingPool contract, it updates deposit accounting and calculates fees based on rewards earned by vaults. These rewards are tracked using the unclaimedRewards and unclaimedOperatorRewards variables in the OperatorVault and OperatorVCS contracts, respectively. The rewards are intended to be converted to LST and sent to OperatorVCS, where operators can claim them via the OperatorVault::withdrawRewards function.

However, the StakingPool::_updateStrategyRewards function, which is responsible for distributing LST, fails to send any rewards to the OperatorVCS contract. Instead, it distributes the entire amount of LST to fee receivers, ignoring the operators entirely.

The relevant portion of the code is shown here:

function _updateStrategyRewards(uint256[] memory _strategyIdxs, bytes memory _data) private {
// ...
// distribute fees to receivers if there are any
if (totalFeeAmounts > 0) {
uint256 sharesToMint = (totalFeeAmounts * totalShares) / (totalStaked - totalFeeAmounts);
_mintShares(address(this), sharesToMint);
uint256 feesPaidCount;
for (uint256 i = 0; i < receivers.length; i++) {
for (uint256 j = 0; j < receivers[i].length; j++) {
if (feesPaidCount == totalFeeCount - 1) {
transferAndCallFrom(
address(this),
receivers[i][j],
balanceOf(address(this)),
"0x"
);
} else {
transferAndCallFrom(address(this), receivers[i][j], feeAmounts[i][j], "0x");
feesPaidCount++;
}
}
}
}
emit UpdateStrategyRewards(msg.sender, totalStaked, totalRewards, totalFeeAmounts);
}

As seen in the code, the LST tokens are minted and distributed only to fee receivers, and there is no logic to handle the distribution of rewards to operators. Even worse, the rewards sent to fee receivers include the portion intended for operators.

Impact

Operators lose out on their rightful share of rewards, as the protocol incorrectly sends all rewards to fee receivers. This misallocation not only affects operator earnings but also causes a broader imbalance in the reward distribution process.

Tools Used

Manual

Recommendations

Update the StakingPool::_updateStrategyRewards function to ensure that LST rewards are properly allocated to operators in addition to fee receivers. Implement a mechanism to transfer the appropriate portion of rewards to the OperatorVCS contract so operators can claim their rewards via OperatorVault::withdrawRewards.

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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