Core Contracts

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

FeeCollector.sol::_calculateDistribution() => Precision loss in FeeCollector's distribution calculation leads to loss of funds for small fee amounts

Summary

The _calculateDistribution function in FeeCollector.sol suffers from precision loss when handling small fee amounts relative to the total fees, potentially leading to incorrect distribution calculations and loss of funds for stakeholders.

Vulnerability Details

In the _calculateDistribution function, the weight calculation for each fee type is performed as:

uint256 weight = (feeAmount BASIS_POINTS) / totalFees;

When feeAmount is significantly smaller than totalFees, this calculation can result in a weight of 0 due to integer division rounding down.

For example:

  • If feeAmount = 100

  • BASIS_POINTS = 10000 as defined in the contract

  • totalFees = 10000000

The calculation becomes: weight = (100 * 10000) / 10000000 = 1000000 / 10000000 = 0

The actual weight should be 0.1, but due to integer division, small amounts get completely rounded down to zero, effectively being ignored in the distribution.

This issue is further compounded because the weights are then used to calculate the final shares:

uint256 weight = (feeAmount * BASIS_POINTS) / totalFees;
shares[0] += (weight * feeType.veRAACShare) / BASIS_POINTS;
shares[1] += (weight * feeType.burnShare) / BASIS_POINTS;
shares[2] += (weight * feeType.repairShare) / BASIS_POINTS;
shares[3] += (weight * feeType.treasuryShare) / BASIS_POINTS;

Impact

  • Small fee amounts may be effectively ignored in distribution calculations

  • Stakeholders may not receive their correct share of fees

  • The distribution proportions defined in feeTypes are not accurately maintained

  • Loss of funds for stakeholders when processing small fee amounts

Tools Used

  • Manual code review and mathematical analysis

Recommendations

  1. consider minimum fee thresholds to prevent dust amounts:

function _calculateDistribution(uint256 totalFees) internal view returns (uint256[4] memory shares) {
uint256 totalCollected;
for (uint8 i = 0; i < 8; i++) {
uint256 feeAmount = _getFeeAmountByType(i);
if (feeAmount == 0) continue;
FeeType memory feeType = feeTypes[i];
totalCollected += feeAmount;
if(feeAmount < MIN_THRESHOLD) revert feeToSmall();

2 Implement fixed-point arithmetic using a library like PRBMath or custom fixed-point calculations:

// Example using 18 decimal fixed-point math
uint256 constant PRECISION = 1e18;
uint256 weightScaled = (feeAmount PRECISION) / totalFees;
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

FeeCollector distributes too much to treasury when fee amounts are small relative to total due to precision loss in (feeAmount * BASIS_POINTS) / totalFees

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

FeeCollector distributes too much to treasury when fee amounts are small relative to total due to precision loss in (feeAmount * BASIS_POINTS) / totalFees

Support

FAQs

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