Core Contracts

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

RAAC Token Swap Tax Not Accounted in FeeCollector, Preventing Reward Distribution

Summary

Whenever RAAC tokens are transferred to non-whitelisted accounts, a tax is deducted from the transferred amount. This tax is supposed to be accounted for in the FeeCollector contract via the collectFee(...) function. However, this does not happen, meaning that the only way to retrieve these funds is through emergencyWithdraw(...), which is not the primary function of the collector.

Vulnerability Details

Each time RAAC tokens are transferred, the update(...) function is executed:

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

In the first super._update(...) call, a portion of the tax is transferred to the FeeCollector. However, the FeeCollector is supposed to distribute RAAC tokens to veRAAC holders according to the following tax distribution structure:

// Buy/Sell Swap Tax (2% total)
feeTypes[6] = FeeType({
veRAACShare: 500, // 0.5%
burnShare: 500, // 0.5%
repairShare: 1000, // 1.0%
treasuryShare: 0
});

This distribution is handled by the distributeCollectedFees() function, which calculates the total fees based on the values stored in collectedFees:

function _calculateTotalFees() internal view returns (uint256) {
return collectedFees.protocolFees +
collectedFees.lendingFees +
collectedFees.performanceFees +
collectedFees.insuranceFees +
collectedFees.mintRedeemFees +
collectedFees.vaultFees +
collectedFees.swapTaxes +
collectedFees.nftRoyalties;
}

However, because the tax is transferred directly to the FeeCollector without being accounted for, none of these storage variables are updated. As a result, the contract does not recognize the collected tax, rendering the reward distribution mechanism ineffective.

Impact

  • The swap tax, which should be accounted for in the FeeCollector, is never properly recorded.

  • The FeeCollector cannot distribute rewards to veRAAC holders as intended.

  • Users will lose their expected share of rewards.

  • The only way to access these funds is via emergencyWithdraw(...), which is not the intended use case.

Tools Used

N/A

Recommendations

To ensure proper tax accounting and reward distribution, the RAAC token contract should explicitly call the collectFee(...) function when processing a transfer. However, due to the current design limitations, a different function should be implemented to correctly account for the tax upon RAAC transfers.

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.