Core Contracts

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

`_calculatePendingRewards` math s wrong, some users won't claim rewards

Summary

_calculatePendingRewards math s wrong, some users won't claim rewards, while other will claim for time that they weren't staked.

Vulnerability Details

_calculatePendingRewards calculates the rewards where each user should get the same amount of rewards proportionate to his voting power percentage of the total.

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

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

However the issue is that reward cycles are 7 days and we get the voting power for the user at this block - veRAACToken.getVotingPower(user), meaning that user can deposit some tokens to get votes on the 6th day and claim rewards proportionate to their voting power percentage, even though they are joining on the last day.

function getVotingPower(address account) public view returns (uint256) {
return _votingState.getCurrentPower(account, block.timestamp);
}

Note that this will also change the math constantly as the voting power increases and decreases over time, with some users getting a huge percentage at the end and failing to claim as most of the rewards were already claimed.

Example:

  1. User has 60 voting power out of 100

  2. He claims 60% of the rewards

  3. Another user increases his voting power to 100, total is 200

  4. The second user tries to claim 50% of the rewards, as he own 50% of the voting power

  5. He is unable as the first user claimed 60% of the rewards, leaving only 40% of them left in the contract.

Impact

Users will be able to claim rewards for a time that they weren't staked, reducing the rewards for users who have participated in the whole journey.

Tools Used

Manual review

Recommendations

Get the block at which the reward cycle was created and use it as for getting the voting power.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Time-Weighted Average Logic is Not Applied to Reward Distribution in `FeeCollector`

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Time-Weighted Average Logic is Not Applied to Reward Distribution in `FeeCollector`

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.