Core Contracts

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

Unbounded Category Allocation

Unbounded Category Allocation

  • Description: The contract allows setting category allocations exceeding total token supply (test_CategoryAllocationExceedsBalance). This creates artificial supply inflation risk.

  • Technical Impact:

    • Enables creation of vesting schedules beyond actual token reserves

    • Leads to insolvent vesting commitments

    • Distorts token economics through phantom allocations

Proof of Concept:

// No supply check in updateCategoryAllocation
function updateCategoryAllocation(bytes32 category, uint256 newAllocation) external {
require(hasRole(ORCHESTRATOR_ROLE, msg.sender), "Unauthorized");
categoryAllocations[category] = newAllocation;
}

test:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../contracts/core/minters/RAACReleaseOrchestrator/RAACReleaseOrchestrator.sol";
import "../contracts/core/tokens/RAACToken.sol";
/**
* @title RAACReleaseOrchestratorVulnerabilitiesTest
* @notice Test suite for identifying and verifying vulnerabilities in the RAACReleaseOrchestrator contract
* @dev These tests focus on edge cases and potential security issues in the vesting mechanism
* Each test simulates real-world scenarios and potential attack vectors
*/
contract RAACReleaseOrchestratorVulnerabilitiesTest is Test {
RAACReleaseOrchestrator public orchestrator;
RAACToken public raacToken;
address public owner;
address public beneficiary;
// Constants from RAACReleaseOrchestrator
uint256 public constant VESTING_CLIFF = 90 days;
uint256 public constant VESTING_DURATION = 700 days;
uint256 public constant MIN_RELEASE_INTERVAL = 1 days;
uint256 public constant GRACE_PERIOD = 7 days;
// Category constants
bytes32 public constant TEAM_CATEGORY = keccak256("TEAM");
bytes32 public constant ADVISOR_CATEGORY = keccak256("ADVISOR");
bytes32 public constant TREASURY_CATEGORY = keccak256("TREASURY");
bytes32 public constant PRIVATE_SALE_CATEGORY = keccak256("PRIVATE_SALE");
bytes32 public constant PUBLIC_SALE_CATEGORY = keccak256("PUBLIC_SALE");
bytes32 public constant LIQUIDITY_CATEGORY = keccak256("LIQUIDITY");
// Role constants
bytes32 public constant ORCHESTRATOR_ROLE = keccak256("ORCHESTRATOR_ROLE");
bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE");
// Additional test addresses
address public treasury;
address public advisor;
address public teamMember;
event VestingScheduleCreated(
address indexed beneficiary,
bytes32 indexed category,
uint256 amount,
uint256 startTime
);
event EmergencyWithdraw(address indexed beneficiary, uint256 amount);
event VestingScheduleRevoked(address indexed beneficiary);
/**
* @notice Set up the test environment
* @dev Deploys fresh instances of RAAC token and ReleaseOrchestrator
* Configures initial roles and token distribution
* Sets up test addresses for different stakeholders
*/
function setUp() public {
owner = address(this);
beneficiary = address(0x1);
treasury = address(0x2);
advisor = address(0x3);
teamMember = address(0x4);
// Deploy RAAC token with initial parameters
// owner, initialSwapTaxRate (1%), initialBurnTaxRate (0.5%)
raacToken = new RAACToken(owner, 100, 50);
// Set minter role to owner
raacToken.setMinter(owner);
// Deploy RAACReleaseOrchestrator
orchestrator = new RAACReleaseOrchestrator(address(raacToken));
// Transfer tokens to orchestrator for vesting
raacToken.mint(address(this), 100_000_000 ether);
raacToken.transfer(address(orchestrator), 100_000_000 ether);
// Log initial setup and configuration
emit log_string("=== Test Environment Setup ===");
emit log_named_address("Owner", owner);
emit log_named_address("Orchestrator", address(orchestrator));
emit log_named_uint("Initial Supply", 100_000_000 ether);
emit log_named_uint("Swap Tax Rate", 100); // 1%
emit log_named_uint("Burn Tax Rate", 50); // 0.5%
emit log_string("===============================");
}
/**
* @notice Test category allocation limits
* @dev Verifies that:
* 1. Category allocations can exceed total token supply
* 2. No validation against contract balance
* 3. This represents a critical vulnerability
*/
function test_CategoryAllocationExceedsBalance() public {
uint256 newAllocation = 200_000_000 ether; // More than total supply
emit log_string("=== Testing Category Allocation Limits ===");
emit log_named_uint("Current Total Supply", raacToken.totalSupply());
emit log_named_uint("Attempted New Allocation", newAllocation);
// Get initial allocation
uint256 initialAllocation = orchestrator.categoryAllocations(TEAM_CATEGORY);
emit log_named_uint("Initial Category Allocation", initialAllocation);
vm.startPrank(owner);
// Should succeed even with allocation > balance
orchestrator.updateCategoryAllocation(TEAM_CATEGORY, newAllocation);
vm.stopPrank();
// Verify new allocation
uint256 finalAllocation = orchestrator.categoryAllocations(TEAM_CATEGORY);
emit log_named_uint("Final Category Allocation", finalAllocation);
assertEq(
finalAllocation,
newAllocation,
"Category allocation should be updated"
);
emit log_string("Vulnerability confirmed: Allocation exceeds total supply");
emit log_string("===============================");
}
}
  • Recommendation:

    • Add supply validation: require(newAllocation <= totalSupply, "Exceeds supply");

    • Implement cross-category allocation checks

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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