Core Contracts

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

amount released by revoked vesting schedules can't be reused to create new vesting schedules

Summary

amount released by revoked vesting schedules can't be reused to create new vesting schedules

Vulnerability Details

When creat vesting schedules, categoryUsed[category] is updated, according to input amount. However, when the schedule is revoked, tokens are transferred back, but categoryUsed[category] is not updated. As a result, the amount release by revoked vesting schedule can't be reused to create new vesting schedules. Please refer to the following steps:

1, categoryAllocations[categoryA] = 100.

2, create 10 vesting schedules, each with amount 10, then categoryUsed[categoryA] = 100.

3, after a while, EMERGENCY_ROLE revoke those 10 schedules, total unreleasedAmount is 90.

4, try to create a new vesting schedule with amount 10, will revert, since categoryUsed[categoryA]=100, categoryAllocations[categoryA] = 100, categoryUsed[categoryA] + amount > categoryAllocations[categoryA], categoryUsed for categoryA is 10 infact.

Impact

although there are enough tokens, new vesting schedules could not be created.

Tools Used

manually reviewed

Recommendations

update categoryUsed[category] in function emergencyRevoke(), since category is not recorded, we could add element 'bytes32 category' in struct VestingSchedule, and record category when create vesting schedule.

struct VestingSchedule {
uint256 totalAmount; // Total amount allocated
uint256 releasedAmount; // Amount already released
uint256 startTime; // Start time of vesting
uint256 duration; // Duration of vesting in seconds
uint256 lastClaimTime; // Last time tokens were claimed
//added
bytes32 category;
bool initialized; // Whether schedule is initialized
}
function emergencyRevoke(address beneficiary) external onlyRole(EMERGENCY_ROLE) {
VestingSchedule storage schedule = vestingSchedules[beneficiary];
if (!schedule.initialized) revert NoVestingSchedule();
uint256 unreleasedAmount = schedule.totalAmount - schedule.releasedAmount;
//added
bytes32 category = schedule.category;
delete vestingSchedules[beneficiary];
if (unreleasedAmount > 0) {
raacToken.transfer(address(this), unreleasedAmount);
//added
categoryUsed[category] = categoryUsed[category] - unreleasedAmount;
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
emit VestingScheduleRevoked(beneficiary);
}
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.