Core Contracts

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

Incorrect Fee Collection Accounting in FeeCollector Due to RAAC Token Tax Mechanism

Summary

The FeeCollector.collectFee() function incorrectly accounts for collected fees by using the pre-tax amount instead of the actual received amount after RAAC token's tax mechanism is applied, leading to accounting inconsistencies and potential issues in fee distribution.

Vulnerability Details

The issue stems from the interaction between two contracts:

The RAAC Token contract implements a tax mechanism in its _update() function, so it is essentially just a Fee-on-transfer token.

The FeeCollector's collection logic in collecting fee:

function collectFee(uint256 amount, uint8 feeType) external override nonReentrant whenNotPaused returns (bool) {
// ...
raacToken.safeTransferFrom(msg.sender, address(this), amount);
// @audit the actual amount received will be less than `amount`
_updateCollectedFees(amount, feeType); // <- @audit Issue here
// ...
}

The core issue is that when raacToken.safeTransferFrom() is called, the actual amount received by the FeeCollector will be less than the input amount due to the RAAC token's tax mechanism. However, the FeeCollector updates its accounting using the pre-tax amount.

For example:

  • If amount = 1000 RAAC

  • Token tax = 1.5% (swapTax 1% + burnTax 0.5%)

  • Actual received = 985 RAAC

  • But accounting records 1000 RAAC

This discrepancy propagates through the system and affects:

  1. The total collected fees calculation (_calculateTotalFees())

  2. The fee distribution calculations (_calculateDistribution())

  3. The actual amounts available for distribution

PoC

  1. Alice calls collectFee() with amount = 1000 RAAC, feeType = 0

  2. Due to RAAC token tax, FeeCollector receives 985 RAAC

  3. FeeCollector records 1000 RAAC in collectedFees.protocolFees

  4. When distributeCollectedFees() is called, it tries to distribute 1000 RAAC

  5. The transaction may revert due to insufficient balance, or distribute incorrect proportions

Impact

  • Incorrect accounting of collected fees

  • Potential reverts in fee distribution

  • Inconsistent reward calculations for veRAAC holders

  • System-wide accounting discrepancies

Tools Used

Manual code review

Recommendations

Modify the collectFee() function to use balance tracking:

function collectFee(uint256 amount, uint8 feeType) external override nonReentrant whenNotPaused returns (bool) {
if (amount == 0 || amount > MAX_FEE_AMOUNT) revert InvalidFeeAmount();
if (feeType > 7) revert InvalidFeeType();
uint256 balanceBefore = raacToken.balanceOf(address(this));
raacToken.safeTransferFrom(msg.sender, address(this), amount);
uint256 actualReceived = raacToken.balanceOf(address(this)) - balanceBefore;
_updateCollectedFees(actualReceived, feeType);
emit FeeCollected(feeType, actualReceived);
return true;
}
Updates

Lead Judging Commences

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.