Core Contracts

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

Incorrect Token Burn Logic When Fee Collection is Disabled

Summary

When fee collection is disabled (i.e., feeCollector == address(0)), the burn function does not correctly burn the full amount of tokens requested by the user. This occurs because the tax calculation is applied regardless of the fee collector's status, causing users to burn less than the intended amount even though no tax is transferred.

Vulnerability Details

In the current implementation of the burn function:

2025-02-raac/contracts/core/tokens/RAACToken.sol at main · Cyfrin/2025-02-raac

When Fee collection is disabled feeCollector == address(0), the burn tax is still subtracted from the amount being burned, but the tax is never transferred since the condition taxAmount > 0 && feeCollector != address(0) fails. This leads to a situation where the deducted tax is effectively lost, and the user burns fewer tokens than requested without the tax being redirected anywhere.

Proof of Concept:

describe("Incorrect Burn Logic", () => {
beforeEach(async () => {
// Declare minter and user1 variables
let minter;
let user1;
[minter, user1] = await ethers.getSigners();
});
it.only("Should burn", async () => {
let ZeroAddress = "0x0000000000000000000000000000000000000000";
// Disable fee collection by setting feeCollector to the Zero Address
await raacToken.connect(owner).setFeeCollector(ZeroAddress);
// Grant minter role to `minter` address
await raacToken.connect(owner).setMinter(minter.address);
// Mint 10,000 tokens to user1
await raacToken.connect(minter).mint(user1.address, 10000);
// Log user1's balance before burning
console.log("Before Burn:", await raacToken.balanceOf(user1.address));
// Attempt to burn all 10,000 tokens from user1
await raacToken.connect(user1).burn(10000);
// Log user1's balance after burning (Expected: 0, but might not be)
console.log("After Burn:", await raacToken.balanceOf(user1.address));
// Expected to be 0, but there's an issue with burn logic
});
});

Outputs:

Before Burn 10000n

After burn 50n

Impact

Exact amount is never burned – Users will attempt multiple burns and never achieve a full burn of their intended amount.

Wasted gas fees – Users must execute multiple transactions, wasting gas to get their full tokens burnt.

Tools Used

Recommendations

To resolve this issue, the burn logic should be adjusted to conditionally apply the tax only when fee collection is enabled. Here’s the corrected implementation:

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

Lead Judging Commences

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