Core Contracts

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

All funds sent to the Treasury contract are permanently lost

Author Revealed upon completion

Vulnerability Details

The Treasury contract has introduced a mapping to track the funds sent called _balances. This mapping is incremented when the deposit function is called and decremented when withdraw occurs.

Problem is: all the funds sent to the Treasury are done via SafeERC20.safeTransfer not the Treaasury.deposit function.

Proof here

Thus, it is impossible to withdraw the funds from the Treasury. Permanently.

Root cause: if (_balances[token] < amount) revert InsufficientBalance();

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();
// @audit-issue _balances[token] is always zero as deposit is never called.
if (_balances[token] < amount) revert InsufficientBalance();
_balances[token] -= amount;
_totalValue -= amount;
IERC20(token).transfer(recipient, amount);
emit Withdrawn(token, amount, recipient);
}

Impact

Permanent loss of all the funds sent to the Treasury. Contract is not upgradeable, there is no way to rescue those funds.

Tools Used

Manual Review

Recommendations

  1. Remove the storage variable _balances. ERC20 already does this tracking for the contract.

  2. Remove the deposit function.

  3. Update the withdraw function to simply send the funds to the recipient as the function is already protected by onlyRole(MANAGER_ROLE).

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;
...
IERC20(token).transfer(recipient, amount);
emit Withdrawn(token, amount, recipient);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 days 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.