Core Contracts

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

Depositing FOT / Tax tokens in the treasury breaks the accounting and emit incorrect event

Summary

The Treasury::deposit function directly stores the passed amount in the _balances and _totalValue, which would lead to incorrect accounting in case of Fee on transfer (FOT) / Tax tokens as the actual amount received by the contract would be low. In addition to this, the event emitted will be incorrect as well as the amount being passed on here is of the parameter itself and not the actual amount received.

Vulnerability Details

The Treasury::deposit function is designed to allow users to deposit any token of their choice, these tokens are tracked via _balances individually and via _totalValue collectively.

function deposit(address token, uint256 amount) external override nonReentrant {
if (token == address(0)) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
IERC20(token).transferFrom(msg.sender, address(this), amount);
_balances[token] += amount; <<@ - // Tracks token balances individually
_totalValue += amount; <<@ - // Tracks overall balances
emit Deposited(token, amount);
}

However, depositing a legit FOT / Tax token would store incorrect amount, as the actual amount received might be lower than the passed amount parameter.
This would show false values to the withdrawer (manager) and the withdraw function might revert as well. It also would emit an incorrect event as the actual amount received by the contract would be different.

Impact

  1. Incorrect accounting of _balances and _totalValue

  2. Withdraw function will revert even though the _balances values are matched with the withdrawing amount parameter.

  3. Incorrect event emission would take place in deposit function as the actual value received will be quite different.

Tools Used

Manual Review
/
Hardhat

Recommendations

It is recommended to handle FOT and tax tokens by checking balance before and after:

function deposit(address token, uint256 amount) external override nonReentrant {
if (amount == 0) revert InvalidAmount();
// Store initial balance before transfer
uint256 balanceBefore = IERC20(token).balanceOf(address(this));
// Perform the transfer
IERC20(token).transferFrom(msg.sender, address(this), amount);
// Calculate actual amount received (handles FOT tokens)
uint256 balanceAfter = IERC20(token).balanceOf(address(this));
uint256 actualAmount = balanceAfter - balanceBefore;
// Update internal accounting with actual amount
_balances[token] += actualAmount;
_totalValue += actualAmount;
emit Deposited(token, actualAmount);
}
Updates

Lead Judging Commences

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

Treasury::deposit increments _totalValue regardless of the token, be it malicious, different decimals, FoT etc.

Treasury::deposit increments _balances[token] with amount, not taking FoT or rebasing into account

Support

FAQs

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