Core Contracts

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

Incorrect rewards distribution logic in FeeCollector

Summary

When users claim their rewards, the following function calculates the amount to receive:

function _calculatePendingRewards(
address user
) internal view returns (uint256) {
uint256 userVotingPower = veRAACToken.getVotingPower(user);
if (userVotingPower == 0) return 0;
uint256 totalVotingPower = veRAACToken.getTotalVotingPower();
if (totalVotingPower == 0) return 0;
uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
return share > userRewards[user] ? share - userRewards[user] : 0;
}

Then the mapping userRewards is updated to the total distributed amount:

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;

The logic is incorrect as it assumes the user has claimed a lot more than what the user has actually claimed, additionally this mechanism only allows user to claim rewards based on the current veToken holdings. Once claimed at a percentage of the total supply, let's say 10%, that user won't ever be entitled to a claim unless he increases the balance.

Vulnerability Details

Users will receive less rewards than what they are entitled to.

Impact

Tools Used

Manual review.

Recommendations

The correct mechanism to handle rewards distribution I'd say is something similar to the guages. Keep track of the total distribution at which a user made a claim and then assign rewards based on the difference between the previous and the current mark times the percentage of the total supply of veTokens held by the user.

Updates

Lead Judging Commences

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

Give us feedback!