Core Contracts

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

Loss of Future Rewards Due to Incorrect Reward Accounting

Summary

The FeeCollector's claimRewards function incorrectly updates user reward tracking by setting it to the total distributed amount instead of adding the claimed amount, causing users to lose access to future rewards.

I should also note that the contract have a function _updateLastClaimTime that looks should be called in claimRewards but isn`t used.

`

Vulnerability Details

function claimRewards(address user) external override nonReentrant whenNotPaused returns (uint256) {
// ...
uint256 pendingReward = _calculatePendingRewards(user);
// Reset user rewards to totalDistributed instead of adding claimed amount
userRewards[user] = totalDistributed;
raacToken.safeTransfer(user, pendingReward);
// ...
}
function _calculatePendingRewards(address user) internal view returns (uint256) {
// ...
uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
return share > userRewards[user] ? share - userRewards[user] : 0;
}

When setting userRewards[user] = totalDistributed:

  1. The user's share is calculated based on total distributed rewards

  2. But their checkpoint is set as if they claimed all rewards ever distributed

  3. Future calculations share - userRewards[user] will revert

Impact

Users lose access to future rewards after their first claim

Tools Used

Manual code review

Recommendations

Track actual claimed amounts instead of total distributed

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();
// Add claimed amount to user's reward checkpoint
userRewards[user] += pendingReward;
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}
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

_updateLastClaimTime not properly used to track rewards claim time

Support

FAQs

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