Core Contracts

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

`claimRewards` prevents users from claiming rewards more than once

Summary

claimRewards bricks after the first claim.

Vulnerability Details

Inside claimRewards after claiming the rewards we set the keeper value (userRewards[user]) to totalDistributed.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/FeeCollector.sol#L199

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();
userRewards[user] = totalDistributed; // <@ set userRewards to total
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}

Where in such math generally userRewards[user] s the value of rewards the user has claimed up to now and it's used to determine the rewards he should receive in the future, as seen here:

return share > userRewards[user]
? share - userRewards[user]
: 0;

However the issue in our case is that this value is set to totalDistributed which is 100% of the rewards that are to be distributed to all users. This will prevent our user from claiming again as the above code will always return 0.

Example:

  1. 10 users, each should get 100 tokens, as each controls 10% of the voting power

  2. mid way user one calls claimRewards and claims 50 tokens, but userRewards[user] is set to 1000

  3. This user would not be able to claim again

Impact

User will only be able to claim a one, meaning that claims that don't claim 100% of the rewards will leave rewards stuck.
This will be even worse if there are multiple reward cycles.

Tools Used

Manual review

Recommendations

Consider setting userRewards to the actual amount claimed by the user.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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.