Core Contracts

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

Stuck Funds in RAACReleaseOrchestrator Contract due to not deducting category used upon emergency revokes.

Summary

In the emergencyRevoke function, when a beneficiary's vesting schedule is revoked, the categoryUsed mapping is not updated to reflect the returned tokens, leaving the allocated space permanently occupied and preventing reuse of the allocation and the funds to be stuck in the contract.

Vulnerability Details

The RAACReleaseOrchestrator contract maintains category allocations and tracks usage through categoryAllocations and categoryUsed mappings. When creating a vesting schedule, categoryUsed is increased to track allocation usage. However, when a schedule is revoked via emergencyRevoke, while the tokens are returned to the contract, the categoryUsed amount remains unchanged. This means the space in the category allocation remains marked as used even though the tokens are no longer allocated to any beneficiary.

This creates an inconsistency between the actual token allocation and the tracked usage, therefore causing loss of the tokens and preventing the reuse of the freed allocation for new beneficiaries even though the tokens are available.

PoC

  1. Admin creates vesting schedule for Alice, Bob and Eve each with 10_000 tokens from TEAM_CATEGORY

  2. categoryUsed[TEAM_CATEGORY] is now 30_000

  3. Emergency role holder revokes Alice's, Bob's and Eve's schedules.

  4. 30_000 tokens return to contract but categoryUsed[TEAM_CATEGORY] remains 30_000

  5. Several several vesting schedules are created until the original categoryAllocations[TEAM_CATEGORY] is just short of 30_000 tokens to be full, at this point categoryUsed[TEAM_CATEGORY] will be full but yet there is still the 30_000 tokens just left stuck in the contract.

  6. When trying to create a new schedule using the same 30_000 tokens, it fails because categoryUsed still shows the space as occupied because of the check if (newCategoryTotal > categoryAllocations[category]) revert CategoryAllocationExceeded();

Impact

  • At the end of the vesting duration all the revoked tokens will be left stuck in the RAACReleaseOrchestrator contract.

  • Inability to reuse freed allocations for new beneficiaries

  • Permanent reduction in effective category allocation capacity

  • Potential DOS of the vesting system when multiple revocations accumulate

Tools Used

Manual Review

Recommendations

function emergencyRevoke(address beneficiary) external onlyRole(EMERGENCY_ROLE) {
VestingSchedule storage schedule = vestingSchedules[beneficiary];
if (!schedule.initialized) revert NoVestingSchedule();
uint256 unreleasedAmount = schedule.totalAmount - schedule.releasedAmount;
// @audit-info Add tracking of category for each schedule
bytes32 category = beneficiaryCategory[beneficiary];
// @audit-info deduct from category used
categoryUsed[category] -= unreleasedAmount;
delete vestingSchedules[beneficiary];
if (unreleasedAmount > 0) {
raacToken.transfer(address(this), unreleasedAmount);
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
emit VestingScheduleRevoked(beneficiary);
}

Note: This requires adding category tracking per beneficiary through a new mapping.

Updates

Lead Judging Commences

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

Give us feedback!