Core Contracts

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

User can't claim rewards for subsequent distribution

Summary

Users cannot claim rewards after their first claim due to incorrect checkpoint logic, where userRewards[user] is set to the entire totalDistributed amount, making subsequent claims always return zero.

Vulnerability Details

In the FeeCollector contract, the claimRewards mechanism has a critical flaw in its checkpoint logic:

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();
// Reset user rewards before transfer
userRewards[user] = totalDistributed; // @audit Sets to total, not user's share
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}

In _calculatePendingRewards, since the serRewards[user] will always be bigger than the share, then it will always return 0.

uint256 share = (totalDistributed userVotingPower) / totalVotingPower;
return share > userRewards[user] ? share - userRewards[user] : 0; // @audit - Always returns 0 after first claim

Impact

Users permanently lose access to new rewards after their first claim due to incorrect checkpoint logic, breaking the protocol's entire reward distribution system.

Tools Used

Manual Review

Recommendations

  1. Set checkpoint to user's share instead of total

  2. Or track claimed amounts instead of shares

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.