Core Contracts

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

FeeController: claimRewards function doesn’t properly track unclaimed/available rewards

Summary

In the FeeController contract, the claimRewards function doesn’t properly track unclaimed rewards. This can cause users to be unable to claim their fair share, leading to the contract reverting.

A common issue occurs when all rewards are distributed and claimed. A user burns their tokens veTokens (veRAACToken.withdraw), reducing the totalVotingPower. This causes each user’s share to increase, but there may not be enough tokens available to claim, causing the claimRewards transaction to fail—even after new rewards have been accumulated.

Vulnerability Details

  1. User B locks 1000 veTokens and is the only one holding veTokens.

  2. User B calls claimRewards and receives 100% of totalDistributed. (note that the contract does not track claimed or available rewards)

  3. User B withdraws and burns veTokens.

  4. User A locks 1000 veTokens for max time. (voting power of A will be 1000)

  5. A calls claimRewards expecting to receive 100% of totalDistributed,

  • user share = userVotingPower/totalVotingPower = 1000/1000 = 1

    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;
    }
  1. Contract tries to transfer rewards (100% of totalDistributed)

  2. leading to an insufficient balance and a revert.

  3. Even after multiple increases in totalDistributed, user can never claim all of totalDistributed since part of it is already claimed and sent to other users.

Impact

Since the contract doesn’t track unclaimed rewards, users may be unable to claim their rightful share of rewards. When users try to claim rewards, the contract might not have enough tokens to send, leading to transaction failures (reverts).

Tools Used

vscode

Recommendations

totalDistribution represents all the rewards that have been accumulated, but the contract doesn’t track how much of it has already been claimed and sent out to users. Because of this, there are situations where there might not be enough tokens to send to users.

By tracking unclaimed rewards, each user can claim their share based on their contribution (or power).

Updates

Lead Judging Commences

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