Core Contracts

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

### Incorrect Reward Tracking in `FeeCollector::claimRewards()` Function

Overview

The claimRewards function is designed to allow users to claim their pending rewards. However, the function contains a critical issue in how it updates the userRewards mapping. Specifically, the function sets userRewards[user] to totalDistributed instead of adjusting it based on the claimed rewards. This can lead to incorrect reward tracking and potential loss of rewards for users.

Vulnerability Details

  1. Functionality of claimRewards:

    • The function calculates the pending rewards for a user using _calculatePendingRewards(user).

    • If the pending rewards are greater than 0, it updates the userRewards mapping and transfers the rewards to the user.

    • The function emits an event (RewardClaimed) to log the reward claim.

  2. Issue with Reward Tracking:

    • The line userRewards[user] = totalDistributed resets the user's reward balance to totalDistributed, which is incorrect.

    • This logic assumes that totalDistributed represents the total rewards distributed so far, but it does not account for the user's previously claimed rewards.

    • As a result, the user's reward balance is overwritten, leading to incorrect tracking of their rewards.

  3. Impact:

    • Incorrect Reward Tracking: Users may lose their pending rewards because the userRewards mapping is not updated correctly.

    • Double-Spending Vulnerability: If totalDistributed is not updated correctly, users may be able to claim rewards multiple times.

    • Economic Loss: Users may not receive the rewards they are entitled to, leading to a loss of trust in the system.

  4. Example Scenario:

    • A user has pending rewards of 100 tokens.

    • The user calls claimRewards, and the function calculates pendingReward = 100.

    • Instead of deducting the claimed rewards from the user's balance, the function sets userRewards[user] = totalDistributed.

    • If totalDistributed is 500, the user's reward balance is incorrectly set to 500, even though they only claimed 100 tokens.

    • The user's pending rewards are effectively reset, and they may lose their remaining rewards.

Here is the problematic code snippet:

function claimRewards(address user) external override nonReentrant whenNotPaused returns (uint256) {
if (user == address(0)) revert InvalidAddress();
uint256 pendingReward = _calculatePendingRewards(user);
if (pendingReward == 0) revert InsufficientBalance();
// Incorrect reward tracking
@> userRewards[user] = totalDistributed;
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}
  • Issue: The line userRewards[user] = totalDistributed resets the user's reward balance to totalDistributed, which is incorrect.

  • Expected Behavior: The function should deduct the claimed rewards (pendingReward) from the user's reward balance in the userRewards mapping.

Recommendations

To fix this issue, update the claimRewards function to correctly adjust the user's reward balance. Here are the steps:

  1. Update Reward Tracking Logic:

    • Instead of setting userRewards[user] = totalDistributed, deduct the claimed rewards (pendingReward) from the user's reward balance.

    • Example:

      userRewards[user] -= pendingReward;
  2. Ensure Consistency:

    • Ensure that userRewards[user] is initialized correctly and updated consistently throughout the contract.

    • If userRewards[user] represents the total rewards earned by the user, ensure that it is updated whenever new rewards are accrued.

  3. Add Safety Checks:

    • Add a check to ensure that userRewards[user] is greater than or equal to pendingReward before deducting the rewards.

      require(userRewards[user] >= pendingReward, "Insufficient rewards balance");
  4. Test the Fix:

    • Write unit tests to verify that the claimRewards function correctly updates the user's reward balance and transfers the correct amount of tokens.

Revised Code Example

Here is the corrected implementation of the claimRewards function:

function claimRewards(address user) external override nonReentrant whenNotPaused returns (uint256) {
if (user == address(0)) revert InvalidAddress();
uint256 pendingReward = _calculatePendingRewards(user);
if (pendingReward == 0) revert InsufficientBalance();
// Ensure the user has sufficient rewards balance
require(userRewards[user] >= pendingReward, "Insufficient rewards balance");
// Deduct claimed rewards from the user's balance
userRewards[user] -= pendingReward;
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}

Conclusion

The claimRewards function currently resets the user's reward balance to totalDistributed, leading to incorrect reward tracking and potential loss of rewards for users. By updating the function to correctly deduct the claimed rewards from the user's balance, the contract will ensure accurate reward tracking and fair distribution of rewards. This fix is critical for maintaining the integrity and trustworthiness of the reward system.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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.