Liquid Staking

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

CommunityVCS::claimRewards Function Fails to Correctly Handle _minRewards Parameter, Leading to Incorrect Reward Claims

Summary

The claimRewards function in the CommunityVCS contract is not correctly handling the _minRewards parameter, leading to incorrect reward claims. This results in a discrepancy between the expected and actual token balances after claiming rewards.

Vulnerability Details

The claimRewards function is designed to claim rewards from specified vaults if the rewards meet or exceed a minimum threshold (_minRewards). However, the function does not correctly check the actual rewards claimed from each vault, leading to incorrect reward claims. Specifically, rewards from vaults that do not meet the _minRewards threshold are still being included in the total claimed rewards.

POC

  • Copy this POC to the exciting test: test/linkStaking/community-vcs.test.ts

it('claimRewards should work correctly', async () => {
const { adrs, strategy, rewardsController, token } = await loadFixture(deployFixture)
let vaults = await strategy.getVaults()
await strategy.deposit(toEther(1000), encodeVaults([]))
// No rewards available //@audit
await strategy.claimRewards([1, 3, 5], toEther(10))
console.log('Balance after no rewards:', fromEther(await token.balanceOf(adrs.strategy)))
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 0)
// Rewards less than _minRewards //@audit
await rewardsController.setReward(vaults[1], toEther(5))
await rewardsController.setReward(vaults[3], toEther(7))
await rewardsController.setReward(vaults[5], toEther(8))
await strategy.claimRewards([1, 3, 5], toEther(10))
console.log(
'Balance after rewards less than _minRewards:',
fromEther(await token.balanceOf(adrs.strategy))
)
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 0)
// Rewards equal to _minRewards //@audit
await rewardsController.setReward(vaults[1], toEther(10))
await strategy.claimRewards([1], toEther(10))
console.log(
'Balance after rewards equal to _minRewards:',
fromEther(await token.balanceOf(adrs.strategy))
)
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 10)
// Rewards greater than _minRewards
await rewardsController.setReward(vaults[6], toEther(10))
await rewardsController.setReward(vaults[7], toEther(7)) // This should not be included
await rewardsController.setReward(vaults[8], toEther(15))
await strategy.claimRewards([6, 8], toEther(10)) // Exclude vault 7
console.log(
'Balance after rewards greater than _minRewards:',
fromEther(await token.balanceOf(adrs.strategy))
)
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 25)
// Multiple claims //@audit
await rewardsController.setReward(vaults[9], toEther(15))
await rewardsController.setReward(vaults[10], toEther(15))
await rewardsController.setReward(vaults[11], toEther(15))
await strategy.claimRewards([9, 10, 11], toEther(10))
console.log('Balance after multiple claims:', fromEther(await token.balanceOf(adrs.strategy)))
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 70)
// Claim with zero _minRewards //@audit
await rewardsController.setReward(vaults[12], toEther(5))
await strategy.claimRewards([12], 0)
console.log(
'Balance after claim with zero _minRewards:',
fromEther(await token.balanceOf(adrs.strategy))
)
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 75)
// Invalid vault index //@audit
await expect(strategy.claimRewards([100], 0)).to.be.reverted
// Empty vault list //@audit
await strategy.claimRewards([], 0)
console.log('Balance after empty vault list:', fromEther(await token.balanceOf(adrs.strategy)))
assert.equal(fromEther(await token.balanceOf(adrs.strategy)), 75)
})
  • Output

Balance after no rewards: 0
Balance after rewards less than _minRewards: 0
Balance after rewards equal to _minRewards: 10
Balance after rewards greater than _minRewards: 35
1) claimRewards should work correctly
4 passing (866ms)
1 failing
1) CommunityVCS
claimRewards should work correctly:
AssertionError: expected 35 to equal 25
+ expected - actual
-35
+25

The test case demonstrates that the claimRewards function incorrectly includes rewards from vaults that do not meet the _minRewards threshold. Specifically, the balance after claiming rewards greater than _minRewards is expected to be 25, but the actual balance is 35, indicating that rewards from vault 7 (which should not be included) are being incorrectly claimed.

Impact

The incorrect handling of the _minRewards parameter in the claimRewards function can lead to over-claiming of rewards, resulting in discrepancies in the expected and actual token balances. This can affect the integrity of the reward distribution mechanism and potentially lead to financial losses. Given the potential for financial discrepancies and the impact on the reward distribution mechanism, the severity of this finding is medium.

Tools Used

  • Hardhat

Recommendations

  • Check Actual Rewards Claimed: Update the claimRewards function to correctly check the actual rewards claimed from each vault. Ensure that only rewards meeting or exceeding the _minRewards threshold are claimed.

  • Access Control: Consider adding access control to the claimRewards function to restrict who can call this function. This can prevent unauthorized users from attempting to claim rewards.

Updates

Lead Judging Commences

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

Support

FAQs

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