Core Contracts

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

Improper validation while changing feeTypes with updateFeeType

Summary

There are different types of fees as mentioned in the protocol. And they are all initialized by _initializeFeeTypes() in the constructor. However in the constructor the summation of :

  • Buy/Swap Sell tax = 2000

  • NFT Royalty Fees = 2000

    However when you update the feeType with the help of updateFeeType() there is a validation that the summation of all the shares of a FeeType = BASIS_POINTS = 10000 which isn't the ideal case and is not enforced even before.

Vulnerability Details

This is what the distribution of the shares of different feeTypes is during the time of initialization. The summation of all the shares of the fee type is expected to be 10_000. However this is not the case even at the time of initialization.

// Protocol Fees: 80% to veRAAC holders, 20% to treasury
feeTypes[0] = FeeType({
veRAACShare: 8000, // 80%
burnShare: 0,
repairShare: 0,
treasuryShare: 2000 // 20%
});
// Lending Fees: Interest income distribution
feeTypes[1] = FeeType({
veRAACShare: 7000, // 70%
burnShare: 0,
repairShare: 0,
treasuryShare: 3000 // 30%
});
// Performance Fees: 20% from yield products
feeTypes[2] = FeeType({
veRAACShare: 6000, // 60%
burnShare: 0,
repairShare: 0,
treasuryShare: 4000 // 40%
});
// Insurance Fees: 3% from NFT loans
feeTypes[3] = FeeType({
veRAACShare: 5000, // 50%
burnShare: 0,
repairShare: 2000, // 20%
treasuryShare: 3000 // 30%
});
// Mint/Redeem Fees
feeTypes[4] = FeeType({
veRAACShare: 6000, // 60%
burnShare: 0,
repairShare: 2000, // 20%
treasuryShare: 2000 // 20%
});
// Vault Fees
feeTypes[5] = FeeType({
veRAACShare: 7000, // 70%
burnShare: 0,
repairShare: 0,
treasuryShare: 3000 // 30%
});
// Buy/Sell Swap Tax (2% total)
feeTypes[6] = FeeType({
veRAACShare: 500, // 0.5%
burnShare: 500, // 0.5%
repairShare: 1000, // 1.0%
treasuryShare: 0
});
// NFT Royalty Fees (2% total)
feeTypes[7] = FeeType({
veRAACShare: 500, // 0.5%
burnShare: 0,
repairShare: 1000, // 1.0%
treasuryShare: 500 // 0.5%
});

And with the udpateFeeType() there is validation which enforces the case :

function updateFeeType(uint8 feeType, FeeType calldata newFee) external override {
if (!hasRole(FEE_MANAGER_ROLE, msg.sender)) revert UnauthorizedCaller();
if (feeType > 7) revert InvalidFeeType();
// Validate fee shares total to 100%
//@audit In the _initializeFeeTypes even there are certain fees which are not 100% in total like swapFees, nftRoyalties. This will cause discrepancy.
if (newFee.veRAACShare + newFee.burnShare + newFee.repairShare + newFee.treasuryShare != BASIS_POINTS) {
revert InvalidDistributionParams();
}
feeTypes[feeType] = newFee;
emit FeeTypeUpdated(feeType, newFee);
}

Impact

FEE MANAAGER cannot modify improperly initialized fee types, breaking protocol upgradeability and potentially locking funds in incorrect distributions. And also while processing fees it is calculated on the basis of 10_000

Tools Used

Manual Review

Recommendations

Align initial fee type shares to sum to BASIS_POINTS or adjust the validation logic to handle variable total shares if intended.

Updates

Lead Judging Commences

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