Core Contracts

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

`RAACToken` contract does not call `collectFee` function when transfering tokens to `FeeCollector`

Summary

FeeCollector contract implements collectFee function which updates collected fees which are later used in distribution calculations. RAACToken contract directly transfers ERC20 tokens. As a result the tokens can't be correctly distributed.

Vulnerability Details

collectFee function is used to increase the collected fees which will be later distributed.

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();
// Transfer tokens from sender
raacToken.safeTransferFrom(msg.sender, address(this), amount);
// Update collected fees
_updateCollectedFees(amount, feeType);
emit FeeCollected(feeType, amount);
return true;
}

In RAACToken contract, when tokens are burned, they are directly transfered to FeeCollector using _transfer function.

function burn(uint256 amount) external {
uint256 taxAmount = amount.percentMul(burnTaxRate);
_burn(msg.sender, amount - taxAmount);
if (taxAmount > 0 && feeCollector != address(0)) {
_transfer(msg.sender, feeCollector, taxAmount);
}
}

Also in _update function the tokens are directly added to FeeCollector address.

function _update(
address from,
address to,
uint256 amount
) internal virtual override {
uint256 baseTax = swapTaxRate + burnTaxRate;
// Skip tax for whitelisted addresses or when fee collector disabled
if (baseTax == 0 || from == address(0) || to == address(0) || whitelistAddress[from] || whitelistAddress[to] || feeCollector == address(0)) {
super._update(from, to, amount);
return;
}
// All other cases where tax is applied
uint256 totalTax = amount.percentMul(baseTax);
uint256 burnAmount = totalTax * burnTaxRate / baseTax;
super._update(from, feeCollector, totalTax - burnAmount);
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}

Impact

FeeCollector expects other contracts to call collectFee function so that collected fees are correctly calculated using state variables. RAACToken sends tokens directly to FeeCollector. As a result, transfered tokens can't be correctly distributed to users and FeeCollector can't work as expected.

Tools Used

Manual Review, Hardhat

Recommendations

Fix burn and _update function in RAACToken contract so that they call collectFee function.

Updates

Lead Judging Commences

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