Core Contracts

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

FeeCollector's `_processDistributions` Function Does Not Handle RAACToken Burn Tax When `FeeCollectionDisabled` is Active, Leading to Token stuck in the `FeeCollector` contract.

Summary

The issue in the RAACToken contract arises due to the interaction between the FeeCollector mechanism and the burn function. When FeeCollectionDisabled is active (feeCollector set to address(0)), no tax is applied upon burning, and the taxAmount remains in the msg.sender account. However, when fees are collected and distributed through distributeCollectedFees, the _processDistributions function attempts to burn shares[1] of RAACToken. If FeeCollectionDisabled is disabled, the amount - taxAmount of RAACToken gets stuck in the FeeCollector contract, as the function does not properly account for this state. This results in unclaimed tokens accumulating in the contract instead of being properly processed or burned.

Vulnerability Details

In the RaacToken contract, the owner can enable or disable the feeCollector address. This logic is implemented in the setFeeCollector function, as seen in FeeCollectionEnabled and FeeCollectionDisabled.

/**
* @dev Sets the fee collector address
* @param _feeCollector The address of the new fee collector
*/
function setFeeCollector(address _feeCollector) external onlyOwner {
// Fee collector can be set to zero address to disable fee collection
if(feeCollector == address(0) && _feeCollector != address(0)){
emit FeeCollectionEnabled(_feeCollector);
}
if (_feeCollector == address(0)){
@>> emit FeeCollectionDisabled();
}
feeCollector = _feeCollector;
emit FeeCollectorSet(_feeCollector);
}

So, upon burning RAACTokens, if the feeCollector address is address(0), it means FeeCollectionDisabled is active. In this case, no tax is applied upon burning, and the taxAmount remains in the msg.sender account, while amount - taxAmount is burned.

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);
}
}

Based on this feature of the RAACToken contract, an issue has occurred in the FeeCollector contract. The problem arises in the distributeCollectedFees function which distributes collected fees according to protocol rules, and calls internal _processDistributions to transfer and allocated these collected fees. Specifically, shares[1] of the RAACToken is burned, So if FeeCollectionDisabled is disabled. As a result, the amount - taxAmount of RAACToken gets stuck in the FeeCollector contract.

function _processDistributions(uint256 totalFees, uint256[4] memory shares) internal {
uint256 contractBalance = raacToken.balanceOf(address(this));
if (contractBalance < totalFees) revert InsufficientBalance();
if (shares[0] > 0) {
uint256 totalVeRAACSupply = veRAACToken.getTotalVotingPower();
if (totalVeRAACSupply > 0) {
TimeWeightedAverage.createPeriod(
distributionPeriod,
block.timestamp + 1,
7 days,
shares[0],
totalVeRAACSupply
);
totalDistributed += shares[0];
} else {
shares[3] += shares[0]; // Add to treasury if no veRAAC holders
}
}
@>> if (shares[1] > 0) raacToken.burn(shares[1]);
if (shares[2] > 0) raacToken.safeTransfer(repairFund, shares[2]);
if (shares[3] > 0) raacToken.safeTransfer(treasury, shares[3]);
}

Impact

The issue causes RAACTokens to get stuck in the FeeCollector contract.

Tools Used

Manual Review

Recommendations

Implement a fallback mechanism to recover or reallocate unclaimed tokens.

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.