Core Contracts

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

Improper handling of `taxAmount` in `burn()` function logic in the `RAACToken.sol`

Summary

The RAACToken burn function calculates taxAmount base on burnTaxRate and burns only amount - taxAmount from the caller's balance. Now if feeCollector != address(0) it transfers the fee. How about when the feeCollector == address(0) a valid configuration set by the setFeeCollector() function that becomes an issue because the fee collector is neither transferred nor burnt, leaving it in the user's position.

Vulnerability Details

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/RAACToken.sol#L80-L87
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);
}
}

This bug stems from feeCollector == address(0) causing the conditional transfer to be skiped if (taxAmount > 0 && feeCollector != address(0)) { _transfer(msg.sender, feeCollector, taxAmount) leaving it with no alternative handling of the taxAmount.

Example:
If user calls burn(1000) with burnTaxRate() = 50(0.5%)
taxAmount = 1000 * 0.005 = 5
amount - taxAmount = 995 is burnt.
if(feeCollector != address(0)), 5 tokens are transferred to feeCollector` reducing user's balance by the full 1,000 tokens burnt.
if(feeCollector == address(0), only 995 tokens are burnt, and the user retains 5 tokens, which will go contrary to the user's expectation of burning 1,000 tokens.

Impact

Users retain tokens they intended to burn, leading to inflated token supply and potential financial discrepancies in systems relying on accurate burn accounting.

This flaw could propagate errors, such as misaligned balances and improper revenue tracking.

Tools Used

Manual review

Recommendations

Modify the full logic to ensure that the full amount is burnt regardless of feeCollector status.

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

Lead Judging Commences

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

RAACToken::burn incorrectly deducts tax amount but doesn't burn or transfer it when feeCollector is address(0), preventing complete token burns

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

RAACToken::burn incorrectly deducts tax amount but doesn't burn or transfer it when feeCollector is address(0), preventing complete token burns

Support

FAQs

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

Give us feedback!