Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

Incorrect Reward Tracking in `claimRewards()` Leads to Claim Denial

Summary

The claimRewards() function in FeeCollector incorrectly updates a user’s claimed rewards to totalDistributed instead of incrementing by pendingReward. This results in incorrect reward tracking, leading to improper distributions and denail of legitimate reward claims by users.

Vulnerability Details

The vulnerability is present in the following code snippet from claimRewards():

// Reset user rewards before transfer
userRewards[user] = totalDistributed;

Instead of incrementing userRewards[user] by the amount being claimed (pendingReward), the function incorrectly sets it to totalDistributed. This results in subsequent user claims being denied due to:

return share > userRewards[user] /** which after the first claim becomes the previous `totalDistributed` */
? share - userRewards[user] : 0;

This check will then default to 0 even though the user has a legitimate share, eg:

Example Scenario

Let's assume the following initial conditions:

  • totalDistributed = 1000 (Total rewards distributed so far)

  • userVotingPower = 10

  • totalVotingPower = 100

  • userRewards[user] = 0 (User has not claimed any rewards yet)

First Claim:

  1. Pending Reward Calculation

    uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
    • share = (1000 * 10) / 100 = 100

    • pendingReward = share - userRewards[user] = 100 - 0 = 100

  2. Incorrect Update of userRewards[user]

    userRewards[user] = totalDistributed; // Incorrectly set to 1000
    • userRewards[user] should have been userRewards[user] += pendingReward, meaning it should be 100, but instead, it is set to 1000.

Second Claim Attempt:

  • Suppose totalDistributed increases to 1500 due to additional rewards being distributed.

  1. Pending Reward Calculation (Second Claim)

    share = (1500 * 10) / 100 = 150
    pendingReward = 0; (since `share > userRewards[user] ? share - userRewards[user] : 0; ` )
    • Since userRewards[user] = 1000, which is greater than the new share (150), the calculation results in 0, effectively denying the user any further claims.

Impact

  1. Incorrect Reward Accounting – Users may receive incorrect reward amounts due to the improper update of userRewards[user].

  2. Denial of legitimate user claims.

Tools Used

  • Manual Code Review

Recommendations

  1. Correct Reward Calculation – Update the claim logic to properly increment the claimed rewards:

    userRewards[user] += pendingReward;
Updates

Lead Judging Commences

inallhonesty Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

FeeCollector::claimRewards sets `userRewards[user]` to `totalDistributed` seriously grieving users from rewards

Support

FAQs

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