Core Contracts

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

Denial of Service (DoS) Vulnerability in Reward Claiming Mechanism

Summary

A critical vulnerability has been identified in the claimRewards function, which can permanently prevent users from claiming their rewards after their first claim. This issue arises due to an incorrect update of the userRewards mapping, leading to an unintended reward lockout. Consequently, affected users will be unable to withdraw their accumulated rewards, resulting in a Denial of Service (DoS) attack.

Vulnerability Details

Root Cause

  1. The _calculatePendingRewards function calculates the user's reward share using the following formula:

    uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
    return share > userRewards[user] ? share - userRewards[user] : 0;
    • A user can only claim rewards if their calculated share exceeds their previously claimed amount.

  2. In claimRewards, after a user successfully claims their rewards for the first time, the function updates their userRewards entry incorrectly:

    userRewards[user] = totalDistributed;
    • totalDistributed represents the cumulative total of all distributed rewards.

    • This results in _calculatePendingRewards returning 0 on subsequent claims, preventing the user from claiming rewards in the future.

Issue Explanation

  • Instead of incrementing userRewards[user] by the claimed amount, it is set to totalDistributed.

  • When a user tries to claim rewards after their first claim, _calculatePendingRewards will almost always return 0, making them permanently ineligible for further claims.

Impact

  • Users can be permanently locked out of claiming rewards after their first successful claim.

  • Prevents reward distribution, leading to financial losses for users.

Tools Used

  • Manual code review

Recommendations

To resolve this issue, userRewards[user] should be updated by incrementing it with the actual claimed amount rather than overriding it with totalDistributed.

Fixed 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();
// Fix: Increment instead of overriding with totalDistributed
userRewards[user] += pendingReward;
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}
Updates

Lead Judging Commences

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