Core Contracts

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

User fund can be stuck if totalDistributed increases at very slow amount and user VotingPower increases very fast.

FeeCollector.sol::claimRewards() ->

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;
// Transfer rewards
raacToken.safeTransfer(user, pendingReward);
emit RewardClaimed(user, pendingReward);
return pendingReward;
}

code snippet for FeeCollector.sol::_calculatePendingRewards -

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;
}

Vulnerability Details

  1. for first call to claimRewards(); let's say totalDistributed = 100, userVotingPower = 100, totalVotingPower = 100.
    share_1 = 100*100/100 = 100, userRewards[user] = 100.

  2. for second call to claimRewards(); let's say totalDistributed = 200, userVotingPower = 150, totalVotingPower = 400.
    share_2 = 200*150/400 = 75

since; share_2 (latest share) < share_1 (old share), the else condition will be executed which means user will get 0
reward. even though user is eligible to get his reward.

Impact

whenever someone will call claimRewards() -> _calculatePendingRewards(), the user will not be able to get the reward due to revertion (if above scenario arises).

Tools Used

Manual

Recommendations

Reconsider architecture

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!