Core Contracts

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

FeeCollector: Incorrect Fee Normalization Leads to Inflated Distributions for Swap Tax and NFT Royalty

Relevant GitHub Links

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/collectors/FeeCollector.sol#L380-L393

Summary

The FeeCollector contract incorrectly normalizes fee distributions for Swap Tax and NFT Royalty types, causing their distributions to be 50x larger than intended. This is due to a mismatch between fee initialization values (20% total) and distribution logic that assumes 100% total.

Vulnerability Details

In FeeCollector.sol, fee types 6 (Swap Tax) and 7 (NFT Royalty) are initialized with shares totaling 2000 basis points (20%):

// Swap Tax (type 6)
feeTypes[6] = FeeType({
veRAACShare: 500, // 0.5%
burnShare: 500, // 0.5%
repairShare: 1000, // 1.0%
treasuryShare: 0
});
// NFT Royalty (type 7)
feeTypes[7] = FeeType({
veRAACShare: 500, // 0.5%
burnShare: 0,
repairShare: 1000, // 1.0%
treasuryShare: 500 // 0.5%
});

However, the distribution logic in _calculateDistribution() treats these percentages as if they should total 10000 basis points (100%):

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;

This normalization error results in:

  • 0.5% becoming 25%

  • 1.0% becoming 50%

Impact

  • Swap Tax and NFT Royalty distributions will be 50x larger than intended

  • Severe misallocation of protocol fees

  • Direct financial impact on all fee recipients

  • Potential protocol insolvency if unchecked

Tools Used

Manual Review

Recommendations

Choose one of these solutions:

  1. Adjust initialization values to total 10000 basis points:

// Swap Tax adjusted (example)
feeTypes[6] = FeeType({
veRAACShare: 250, // 2.5%
burnShare: 250, // 2.5%
repairShare: 500, // 5%
treasuryShare: 0
});
  1. Add special handling for these fee types:

uint256 weight;
if (i == 6 || i == 7) {
weight = (feeAmount * 100) / totalFees; // Scale by 100 instead of BASIS_POINTS
} else {
weight = (feeAmount * BASIS_POINTS) / totalFees;
}
  1. Create separate distribution logic for percentage-based vs basis point fees.

Updates

Lead Judging Commences

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

Fee shares for fee type 6 and 7 inside FeeCollector do not total up to the expected 10000 basis points, this leads to update problems, moreover they are 10x the specifications

Support

FAQs

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

Give us feedback!