Core Contracts

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

In `FeeCollector`, Users will always LOSE Future `pendingRewards`

Summary

Function claimRewards() in FeeCollector assigns WHOLE value of totalDistributed to userRewards mapping, this leads to incorrect comparison _calculatePendingRewards , which results in User losing rewards in the future distribution of fees.

Vulnerability Details

Users can claim their accumulated rewards via claimRewards() in FeeCollector contract.

However, the computation of pendingReward is incorrect i.e.
pendingReward()

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

Observe the computation of share, it is calculated based on voting power of the user.
Next, it is compared against the mapping userRewards which is incorrect.

Reason being, this userRewards mapping is later updated to totalDistributed.

Meaning, for a completely new user, this would work as intended.

However, when he makes a second claim or for an old User, this would always lead to a revert.

This happens because the share(of user) would never EXCEED the old value of state variable userReward whose value got updated to totalDistributed in previous fee distribution.

So, although users are eligible and SHOULD be paid the pendingReward, but due to issue in the logic, they will be unable to claim any subsequent rewards after the first one.

Impact

Users will lose future rewards.

Tools Used

Manual

Recommendations

Consider using this instead:

function _calculatePendingRewards(address user) internal view returns (uint256) {
//didn't include voting power as its not needed here for the fix
- uint256 share = (totalDistributed * userVotingPower) / totalVotingPower;
- return share > userRewards[user] ? share - userRewards[user] : 0;
+ if (totalDistributed > userRewards[user]) {
+ uint256 Increment = totalDistributed - userRewards[user] ;
//now, whether we have a percent increase or decrease in voting power,
it would be directly computed on the incremented value.
+ uint256 pending = (Increment * userVotingPower) / totalVotingPower;
+ return pending;
}
+ return 0;
}
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.