Core Contracts

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

Incorrect Reward Checkpoint Prevents Future Reward Claims Due to Arithmetic Comparison

Summary:

The FeeCollector contract's 'claimRewards' contains a critical flaw in its checkpoint logic. By setting userRewards[user] = totalDistributed, the contract prevents users from claiming future rewards because the calculated share will always be less than their checkpoint value.

Vulnerability Details:

In the claimRewards function:

function claimRewards(address user) external override nonReentrant whenNotPaused returns (uint256) {
// ... validation checks ...
// Problematic checkpoint
userRewards[user] = totalDistributed; // Sets checkpoint to total rewards
raacToken.safeTransfer(user, pendingReward);
// ... rest of function
}

The issue arises because of the reward calculation in _calculatePendingRewards:

uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
return share > userRewards[user] ? share - userRewards[user] : 0;

Mathematical proof of the issue:

  1. After first claim: userRewards[user] = totalDistributed

  2. For any subsequent claim:

    • share = (totalDistributed * userVotingPower) / totalVotingPower

    • Since userVotingPower < totalVotingPower, then share < totalDistributed

    • Therefore share < userRewards[user] always

    • Result: returns 0, making rewards unclaimable

Impact:

  • Users can only claim rewards once

  • All subsequent reward distributions become unclaimable

  • Breaks the entire reward distribution mechanism

  • Loss of funds for users who should receive rewards

Tools Used:

Manual code review

Recommendations:

  • Track claimed amount instead of total distributed.

  • Alternative: Use distribution index tracking or use a cumulative rewards per share approach.

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.