Core Contracts

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

Some `raacToken`s will be stuck in `Treasury` contract

Summary

the emergencyWithdraw function in FeeCollector contract, transfers raac tokens to the Treasury contract if token address is raac token. the issue is these tokens will be stuck in Treasury contract forever.

Vulnerability Details

The Treasury contract have deposit() and withdraw() functions, and the logic is allows only funds that comes from deposit() function can be withdrawn:

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

the issue is emergencyWithdraw() function in FeeCollector contract sends raac tokens by using safeTransfer() not deposit() function of Treasury contract:

function emergencyWithdraw(address token) external override whenPaused {
if (!hasRole(EMERGENCY_ROLE, msg.sender)) revert UnauthorizedCaller();
if (token == address(0)) revert InvalidAddress();
uint256 balance;
if (token == address(raacToken)) {
balance = raacToken.balanceOf(address(this));
raacToken.safeTransfer(treasury, balance);
} else {
balance = IERC20(token).balanceOf(address(this));
SafeERC20.safeTransfer(IERC20(token), treasury, balance);
}
emit EmergencyWithdrawal(token, balance);
}

therefor all of the raac tokens that directly sends to Treasury contract will be stuck because there is no way to withdraw it because the _balances mapping doesnt updated so withdraw() will be revert by underflow.

Impact

Some raac tokens will be stuck in Treasury contract for ever.

Tools Used

Manual Review

Recommendations

Consider using deposit() function of Treasury contract when transfering funds.

Updates

Lead Judging Commences

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