Core Contracts

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

Malicious Token Deposit Can Permanently Disable `Treasury` Contract

Summary

The Treasury contract’s deposit function lacks safeguards against whitelist tokens. A malicious actor can exploit this by depositing a custom ERC20 token with an astronomically large amount (e.g., uint256.max), causing the _totalValue state to overflow. This permanently disrupts the treasury’s accounting system, blocking all future deposits and rendering the contract unusable.

Vulnerability Details

In the Treasury:deposit contract, users deposit tokens into the treasury, updating the _balances of the specific token and _totalValue. The issue is that there is no validation on the token address, allowing a malicious user to create a fake ERC-20 token, deposit uint256.max, and set _totalValue to its maximum. This would cause an overflow, preventing any further deposits due to a revert.

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

An attacker can create a custom ERC20 token that allows minting arbitrarily large amounts (e.g., uint256.max), approve the treasury to spend these tokens, and call deposit to force an overflow.

Attack Scenario

  1. Attacker Deploys Malicious Token:

    • The token’s transferFrom function permits minting uint256.max tokens without actual supply checks.

  2. Attacker Deposits uint256.max Tokens:

    maliciousToken.approve(treasuryAddress, type(uint256).max);
    treasury.deposit(address(maliciousToken), type(uint256).max);
  3. State Variables Overflow:

    • _totalValue set to uint256.max.

  4. Legitimate Deposits Fail:

    • Subsequent deposits for any token will revert on _totalValue += amount because _totalValue is already at uint256.max.

Impact

  • Permanent Treasury Disruption: All deposits are blocked after the overflow, rendering the treasury non-functional.

Tools Used

Manual Review

Recommendations

Restrict deposits to whitelisted tokens or verify token compliance:

mapping(address => bool) public allowedTokens;
function deposit(address token, uint256 amount) external override nonReentrant {
require(allowedTokens[token], "Token not whitelisted");
// ... rest of logic ...
}
Updates

Lead Judging Commences

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

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

Support

FAQs

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

Give us feedback!