Core Contracts

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

Allocators can assign funds that don't exist, leading to incorrect accounting

Summary

The Treasury contract allows fund allocation before any actual deposits are made. This could lead to inconsistencies in fund management and potential misinterpretation of available funds.

Vulnerability Details

The Treasury::allocateFunds function enables allocators to assign funds to recipients without verifying whether the Treasury holds sufficient balance. This means allocations can be recorded without any real backing, leading to potential issues when funds need to be distributed.

Impact

  • Misleading fund tracking within the Treasury contract.

  • Potential operational inefficiencies if allocations exceed actual deposits.

  • Increased risk of erroneous fund distributions if not managed properly.

Severity: Medium

Reasoning:

Not directly exploitable: This issue does not allow direct theft of funds or unauthorized access.

Can cause operational issues: Misleading fund tracking can lead to mismanagement, potentially affecting treasury operations.

Depends on implementation: If allocations are used for financial decision-making (e.g., commitments to pay vendors or distribute rewards), this can cause real-world problems.

Proof of concept

Steps to Exploit:

  1. The allocator (a user with the ALLOCATOR_ROLE) calls the Treasury::allocateFunds function to assign funds to a recipient.

  2. The function records the allocation without checking if the Treasury has sufficient balance.

  3. Confirm that the allocation is recorded successfully, while the total Treasury balance remains 0.

contract FeeCollectorTest is Test {
Treasury treasury;
MockToken token;
address owner;
address user1;
address user2;
address manager;
address allocator;
uint256 constant BASIS_POINTS = 10000;
uint256 constant WEEK = 7 * 24 * 3600;
uint256 constant ONE_YEAR = 365 * 24 * 3600;
uint256 constant INITIAL_MINT = 10_000 ether;
uint256 constant SWAP_TAX_RATE = 100; // 1%
uint256 constant BURN_TAX_RATE = 50; // 0.5%
bytes32 constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
bytes32 constant ALLOCATOR_ROLE = keccak256("ALLOCATOR_ROLE");
function setUp() public {
owner = makeAddr("owner");
user1 = makeAddr("user1");
user2 = makeAddr("user2");
vm.startPrank(owner);
treasury = new Treasury(owner);
token = new MockToken("Test Token", "TEST", 18);
token.mint(user1, 1000 ether);
token.mint(user2, 1000 ether);
treasury.grantRole(MANAGER_ROLE, manager);
treasury.grantRole(ALLOCATOR_ROLE, allocator);
vm.stopPrank();
}
function testFundAllocationWithNoFunds() public {
vm.prank(allocator);
treasury.allocateFunds(user1, 100 ether);
assertEq(treasury.getAllocation(allocator, user1), 100 ether);
assertEq(treasury.getTotalValue(), 0);
}
}

Tools Used

Manual code review

Recommendations

  • Implement a check in the Treasury::allocateFunds function to ensure that the allocated amount does not exceed the actual balance of the Treasury.

  • Introduce an additional mapping to track unallocated balances separately.

  • Consider modifying the function to allocate only from existing deposits rather than allowing unrestricted assignments.

Updates

Lead Judging Commences

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

Treasury::allocateFunds doesn't say what token you are actually allocating, doesn't check balances, or existing allocations to other recipients

Support

FAQs

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