Core Contracts

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

Not compliant with fee-on-transfer RAACToken.

Summary

From `RAACToken.sol` we can see it's a fee-on-transfer token , which means receiver will receive less assets than expected.However protocol interact with RAACToken without calculate the actural amount.

Vulnerability Details

function _update(
address from,
address to,
uint256 amount
) internal virtual override {
uint256 baseTax = swapTaxRate + burnTaxRate; //@audit-info 1.5%
// 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); //@audit-info amt * 1.5% //@audit calculate the diff bwt those two options.
uint256 burnAmount = totalTax * burnTaxRate / baseTax; //@audit-info amt * 1.5% * 0.5% / 1.5% == amt * 0.5%
super._update(from, feeCollector, totalTax - burnAmount); //@audit swapTax amount is not tracked.
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}

From above code we can see receiver need to pay tax while transfer assets. However when interact with raccToken protocol use transfer amount as actual amount.

eg1:

veRACCToken.sol

function lock(uint256 amount, uint256 duration) external nonReentrant whenNotPaused {
if (amount == 0) revert InvalidAmount();
if (amount > MAX_LOCK_AMOUNT) revert AmountExceedsLimit();
if (totalSupply() + amount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
if (duration < MIN_LOCK_DURATION || duration > MAX_LOCK_DURATION)
revert InvalidLockDuration();
// Do the transfer first - this will revert with ERC20InsufficientBalance if user doesn't have enough tokens
raacToken.safeTransferFrom(msg.sender, address(this), amount); //@audit racc is fee-on-transfer token.

eg2:

FeeCollector.sol

function collectFee(uint256 amount, uint8 feeType) external override nonReentrant whenNotPaused returns (bool) {
if (amount == 0 || amount > MAX_FEE_AMOUNT) revert InvalidFeeAmount(); //@audit-info range from 0-1_000_000e18.
if (feeType > 7) revert InvalidFeeType();
// Transfer tokens from sender
raacToken.safeTransferFrom(msg.sender, address(this), amount);//@audit racc cost fee.
// Update collected fees
_updateCollectedFees(amount, feeType);//@audit-info track the total collect fee amount.
emit FeeCollected(feeType, amount);
return true;
}

Impact

calculation error

Tools Used

Eye

Recommendations

calculate the actural receive amount

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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