Core Contracts

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

FeeCollector does not utilize the `deposit` function in the Treasury contract which could lead to stuck fees

Summary

FeeCollector distributes the fees to a treasury address through a direct transfer call. This will bypass the accounting logic in deposit which can cause the call to withdraw to revert.

Vulnerability Details

FeeCollector handles the distribution of fees to different actors. One of these actors is the project treasury. If we take a look at _processDistributions, it makes a direct transfer call to the treasury address. This is problematic when we look at the deposit logic in the treasury contract. There is an accounting variable _balances that keeps track of the amount of a token deposited into the treasury.

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;
_totalValue += amount;
emit Deposited(token, amount);
}

When a manager attempts to withdraw this token, there is a check in withdraw to ensure there is a sufficient amount of the token through the _balances variable. The problem is this variable does not account for tokens transferred directly to this contract. If all the funds are being directly transferred to this contract, that check will revert resulting in all of the tokens being stuck.

function withdraw(
address token,
uint256 amount,
address recipient
) external override nonReentrant onlyRole(MANAGER_ROLE) {
if (token == address(0)) revert InvalidAddress();
if (recipient == address(0)) revert InvalidRecipient();
if (_balances[token] < amount) revert InsufficientBalance();
_balances[token] -= amount;
_totalValue -= amount;
IERC20(token).transfer(recipient, amount);
emit Withdrawn(token, amount, recipient);
}

Impact

Loss a fees for the project treasury

Tools Used

Manual Review

Recommendations

Deposit the fees into the treasury contract rather than doing a direct transfer.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

FeeCollector::_processDistributions and emergencyWithdraw directly transfer funds to Treasury where they get permanently stuck

Support

FAQs

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