Core Contracts

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

Category Mismanagement in `RAACReleaseOrchestrator` Vesting Schedules

Summary

The RAACReleaseOrchestrator contract increases the categoryUsed counter when a vesting schedule is created but never decreases it when tokens are released. This oversight causes the categoryUsed value to permanently reflect the initial allocation, potentially blocking further vesting schedule creations even after tokens have been released.

Vulnerability Details

When a new vesting schedule is created in createVestingSchedule function, the function updates the categoryUsed counter as follows:

function createVestingSchedule(
address beneficiary,
bytes32 category,
uint256 amount,
uint256 startTime
) external onlyRole(ORCHESTRATOR_ROLE) whenNotPaused {
if (beneficiary == address(0)) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
if (vestingSchedules[beneficiary].initialized) revert VestingAlreadyInitialized();
if (categoryAllocations[category] == 0) revert InvalidCategory();
// Check category allocation limits
@>> uint256 newCategoryTotal = categoryUsed[category] + amount;
@>> if (newCategoryTotal > categoryAllocations[category]) revert CategoryAllocationExceeded();
@>> categoryUsed[category] = newCategoryTotal;
VestingSchedule storage schedule = vestingSchedules[beneficiary];
schedule.totalAmount = amount;
schedule.startTime = startTime;
schedule.duration = VESTING_DURATION;
schedule.initialized = true;
emit VestingScheduleCreated(beneficiary, category, amount, startTime);
}
  • Issue:
    The categoryUsed value is incremented by the total amount allocated in the vesting schedule. However, when tokens are released from the schedule via the release() function or emergencyRevoke function, the categoryUsed counter is not decremented, meaning that the allocation remains permanently occupied.

function release() external nonReentrant whenNotPaused {
address beneficiary = msg.sender;
VestingSchedule storage schedule = vestingSchedules[beneficiary];
if (!schedule.initialized) revert NoVestingSchedule();
uint256 releasableAmount = _calculateReleasableAmount(schedule);
if (releasableAmount == 0) revert NothingToRelease();
schedule.releasedAmount += releasableAmount;
schedule.lastClaimTime = block.timestamp;
raacToken.transfer(beneficiary, releasableAmount);
emit TokensReleased(beneficiary, releasableAmount);
}
  • Proof-of-Concept (POC):

    1. Initial State:

      • Assume categoryAllocations[TEAM_CATEGORY] is set to 18,000,000 tokens.

      • A vesting schedule is created for a beneficiary with an amount of 1,000,000 tokens.

    2. Creation:

      • categoryUsed[TEAM_CATEGORY] increases by 1,000,000 tokens.

    3. Release:

      • Over time, the beneficiary releases the full 1,000,000 tokens.

      • However, categoryUsed[TEAM_CATEGORY] remains at 1,000,000 tokens.

    4. Subsequent Vesting Schedule:

      • If another vesting schedule is attempted in the TEAM category with an amount of 1 token, the new total becomes 1,000,001 tokens.

      • If this exceeds the remaining allocation limit, the function will revert with CategoryAllocationExceeded(), even though the initial 1,000,000 tokens have already been released.

Impact

The permanent increase in the categoryUsed counter prevents further vesting schedule creations for a category once its allocation is reached, even if tokens have already been released.

Tools Used

Manual Review

Recommendations

Modify the vesting schedule to store its category and update the release() function to subtract the released tokens from the corresponding categoryUsed. This ensures that tokens released free up allocation for future vesting schedules. For example:

Updates

Lead Judging Commences

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

RAACReleaseOrchestrator::emergencyRevoke fails to decrement categoryUsed, causing artificial category over-allocation and rejection of valid vesting schedules

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

RAACReleaseOrchestrator::emergencyRevoke fails to decrement categoryUsed, causing artificial category over-allocation and rejection of valid vesting schedules

Support

FAQs

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