Core Contracts

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

All funds transferred directly to the treasury will be locked permanently.

Summary

Tokens should be transferred to the treasury via the deposit function. However, in several cases, tokens are directly transferred to the treasury. Therefore, the tokens transferred directly to the treasury will be locked permanently due to underflow.

Vulnerability Details

Tokens should be transferred to the treasury via the deposit function.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/Treasury.sol#L46-L55

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

However, in several cases, tokens are directly transferred to the treasury.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/Treasury.sol#L269-L283

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

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/Treasury.sol#L401-L424

function _processDistributions(uint256 totalFees, uint256[4] memory shares) internal {
[... ...]
@> if (shares[3] > 0) raacToken.safeTransfer(treasury, shares[3]);
}

The tokens transferred directly to the treasury will be locked permanently, because _balances[token] and _totalValue is not increased.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/Treasury.sol#L64-L78

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

All funds transferred directly to the treasury will be locked permanently.

Recommendations

Tokens should be transferred to the treasury via the deposit function.

Updates

Lead Judging Commences

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

Give us feedback!