Core Contracts

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

Insecure Fund Allocation System

Summary

The Treasury contract's fund allocation system contains issues that could lead to over-allocation of funds, double-allocation attacks, and permanent allocation locks. The system lacks essential validation checks and proper allocation lifecycle management.

Vulnerability Details

The vulnerabilities manifest in several areas:

Missing Total Allocation Validation

function allocateFunds(address recipient, uint256 amount) external override onlyRole(ALLOCATOR_ROLE) {
if (recipient == address(0)) revert InvalidRecipient();
if (amount == 0) revert InvalidAmount();
_allocations[msg.sender][recipient] = amount; // No validation against total funds
emit FundsAllocated(recipient, amount);
}
  • No check if total allocations exceed available funds

  • Multiple allocators can over-allocate the same funds

  • No tracking of total allocated amounts per token

Allocation State Management Issues

mapping(address => mapping(address => uint256)) private _allocations; // Allocator => recipient => amount
  • No mechanism to remove or expire allocations

  • Allocations persist even if funds are withdrawn

  • No tracking of allocation status (pending/active/completed)

Token-Specific Allocation Problems

  • Allocations are not tied to specific tokens

  • No validation against token balances

  • Generic amount allocation without token context

Impact

  • Multiple allocators can allocate the same funds

  • Total allocations can exceed available treasury funds

  • No protection against double-allocation attacks

  • No way to safely remove outdated allocations

  • Permanent allocation records even after fund withdrawal

  • Difficulty in tracking real available funds

Example Attack Scenarios
Scenario 1: Over-allocation Attack

Initial State:
- Treasury has 1000 USDC
- Allocator A allocates 800 USDC to Recipient X
- Allocator B allocates 800 USDC to Recipient Y
Result: 1600 USDC allocated from 1000 USDC balance

Scenario 2: Withdrawal-Allocation Race

1. Allocator allocates 500 USDC to Recipient
2. Manager withdraws 500 USDC
3. Allocation of 500 USDC remains valid despite no funds
4. New deposits could be immediately claimed by stale allocation
## Recommendations
- Implement Token-Specific Allocation Tracking:
```solidity
mapping(address => mapping(address => mapping(address => uint256))) private _allocations; // token => allocator => recipient => amount
Add Total Allocation Validation:
solidity
CopyInsert
function allocateFunds(address token, address recipient, uint256 amount) external {
uint256 totalAllocated = getTotalAllocated(token);
if (totalAllocated + amount > _balances[token]) revert ExceedsAvailable();
_allocations[token][msg.sender][recipient] = amount;
}

Add Allocation Lifecycle Management:

  • solidity
    enum AllocationStatus { PENDING, ACTIVE, COMPLETED, CANCELLED }
    struct Allocation {
    uint256 amount;
    AllocationStatus status;
    uint256 expiryTime;
    }

- Implement Allocation Expiry:
Updates

Lead Judging Commences

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