Core Contracts

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

Precision loss when calculating rewardRate

Summary

Precision loss will cause users to receive a portion less of the amount to be distributed to them as reward.

Vulnerability Details

Solidity truncates decimal points to zero, hence the reward rate will be subjected to precision issues

function notifyReward(
PeriodState storage state,
uint256 amount,
uint256 maxEmission,
uint256 periodDuration
) internal view returns (uint256) {
if (amount > maxEmission) revert RewardCapExceeded(); // double check this is not neccessary
if (amount + state.distributed > state.emission) {
revert RewardCapExceeded();
}
@audit>> uint256 rewardRate = amount / periodDuration; // BUG medium scale this loss of reward // Rewards being distributed before is not included in reward rate lead to lost rewards
if (rewardRate == 0) revert ZeroRewardRate(); // see
return rewardRate;
}

We prevent RewardRate from being 0 but this doesn't take away the precision issues in the contract.

FOR RWA Guage the period is 1 month , while for RAAC gauge it is 1 week, the higher the duration the higher the amount lost due to this truncation.

E.g distribute 1 WBTC and 7000 USDC in 7days

  1. Reward Rate= 1*1e8 / 7 days = 165.3439153

  2. solidity will return = 165

  3. 165 * 7 days = 99792000.

  4. 1e8 - 99792000 = 208000.

  5. 208000 convert to USDC = 199.68

7000 USD

  1. Reward Rate= 7000*1e6 / 7 days = 11574.07407

  2. solidity will return = 11574

  3. 11574 * 7 days = 6999955200.

  4. 7000000000 - 6999955200 = 44800.

For low decimal ERC20 compliant tokens a huge loss will be observed per distribution this loses id over 190 USD for a token like WBTC.

Already we will scale during the reward pertoke stored calculation, why not scale in the Reward rate calculation instead to catch all precision loss issues.

/**
* @notice Calculates current reward per token
* @return Current reward per token value
*/
function getRewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored + (
@audit >> (lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * 1e18 / totalSupply() // bug before timing // now we decide to scale precion loss don happen for front
);
}

Tools Used

Manual Review

Recommendations

Store the rewardRate scaled by 1e18, so loss of precision will be lower by magnitude of 1e18.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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