Core Contracts

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

Pending fee not cleared and overwritten by updates via updateFeeType()

Description

The FeeCollector contract has a vulnerability where changing fee distribution rates via updateFeeType() can lead to incorrect distribution of previously collected fees. When fee type rates are updated, there is no mechanism to ensure that pending undistributed fees are handled according to the rates that were in effect when they were collected.

function _initializeFeeTypes() internal {
feeTypes[0] = FeeType({
veRAACShare: 8000, // 80%
burnShare: 0,
repairShare: 0,
treasuryShare: 2000 // 20%
});
// .. Rest of code
// Fees get collected but not distributed
function collectFee(uint256 amount, uint8 feeType) external {
// ... fee collection logic
_updateCollectedFees(amount, feeType);
// ... Rest of code
}
function updateFeeType(uint8 feeType, FeeType calldata newFee) external {
// ... validation logic
feeTypes[feeType] = newFee; // Directly overwrites old rates
emit FeeTypeUpdated(feeType, newFee);
}
function distributeCollectedFees() external {
if (!hasRole(DISTRIBUTOR_ROLE, msg.sender)) revert UnauthorizedCaller();
uint256 totalFees = _calculateTotalFees();
if (totalFees == 0) revert InsufficientBalance();
uint256[4] memory shares = _calculateDistribution(totalFees);
_processDistributions(totalFees, shares);
delete collectedFees; // Clears all fee records
emit FeeDistributed(shares[0], shares[1], shares[2], shares[3]);
}
function _calculateDistribution(uint256 totalFees) internal view returns (uint256[4] memory shares) {
// Uses current feeTypes rates for ALL collected fees
for (uint8 i = 0; i < 8; i++) {
uint256 feeAmount = _getFeeAmountByType(i);
if (feeAmount == 0) continue;
FeeType memory feeType = feeTypes[i]; // Uses updated rates
// ... distribution calculation
}
}

As a side note, it should be observed that _processDistributions() called from inside distributeCollectedFees() can revert at if (contractBalance < totalFees) revert InsufficientBalance();. So simply calling it before updateFeeType() may not be sufficient as a mitigation to the issue.

Impact

Incorrect Distribution: Fees collected under one rate structure could be distributed using different rates, violating the expected distribution rules at the time of collection.

Mitigation

  • Force distribute any pending fee first before updating with new fee values.

  • Alternatively, make an entry inside some variable so that they can be distributed later. This will require additional code to make sure new fee values do not effect this old fund of pending fees.

Updates

Lead Judging Commences

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

FeeCollector::updateFeeType applies new distribution parameters retroactively to already collected fees, allowing governance to change expected distribution outcomes before execution

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

FeeCollector::updateFeeType applies new distribution parameters retroactively to already collected fees, allowing governance to change expected distribution outcomes before execution

Support

FAQs

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

Give us feedback!