Core Contracts

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

Incorrect fee collection in RAACToken leads to incorrect fee distribution and locked tokens

Summary

The RAACToken contract directly transfers tax fees to the fee collector without using the FeeCollector::collectFee() function, causing incorrect fee tracking and distribution.

Vulnerability Details

The RAACToken::_update() function directly transfers tax fees to the fee collector address instead of properly collecting fees through the FeeCollector::collectFee() function. This bypasses the fee tracking mechanism in the FeeCollector contract.

The issue occurs in RAACToken::_update():

function _update(address from, address to, uint256 amount) internal virtual override {
// ...
uint256 totalTax = amount.percentMul(baseTax);
uint256 burnAmount = totalTax * burnTaxRate / baseTax;
// Directly transfers to fee collector instead of using collectFee
super._update(from, feeCollector, totalTax - burnAmount);
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}

The FeeCollector contract expects fees to be collected through its collectFee function which updates the CollectedFees tracking structure:

function collectFee(uint256 amount, uint8 feeType) external override nonReentrant whenNotPaused returns (bool) {
// ...
_updateCollectedFees(amount, feeType);
// ...
}

Proof of Concept

  1. User transfers 1000 RAAC tokens with 1% swap tax and 0.5% burn tax

  2. RAACToken::_update calculates total tax of 15 tokens (10 swap + 5 burn)

  3. 5 tokens are burned and 10 tokens are directly transferred to fee collector

  4. The FeeCollector::collectedFees structure is not updated

  5. When distributeCollectedFees is called, these 10 tokens are not included in distribution calculations

  6. veRAAC holders receive fewer rewards than they should

Impact

  • Fees sent directly to the fee collector are not tracked in the CollectedFees structure

  • This leads to incorrect fee distribution calculations

  • veRAAC holders receive fewer rewards than entitled

  • Protocol statistics and accounting are inaccurate

  • Fees become permanently locked in the fee collector contract

Recommendations

Use FeeCollector.collectFee
Modify RAACToken::_update to use the proper fee collection mechanism:

function _update(address from, address to, uint256 amount) internal virtual override {
uint256 totalTax = amount.percentMul(baseTax);
uint256 burnAmount = totalTax * burnTaxRate / baseTax;
- super._update(from, feeCollector, totalTax - burnAmount);
+ super._update(from, address(this), totalTax - burnAmount);
+ IERC20(address(this)).approve(feeCollector, totalTax - burnAmount);
+ IFeeCollector(feeCollector).collectFee(totalTax - burnAmount, 6); // Type 6 for swap tax
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}
Updates

Lead Judging Commences

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

RAACToken::burn sends tax directly to FeeCollector without using collectFee(), causing tokens to bypass accounting and remain undistributed. `collectFee` is not used anywhere.

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

RAACToken::burn sends tax directly to FeeCollector without using collectFee(), causing tokens to bypass accounting and remain undistributed. `collectFee` is not used anywhere.

Support

FAQs

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

Give us feedback!