Summary
RAACReleaseOrchestrator contract is used for vesting purposes but it lacks intial minting of token based on the category allocation.
Vulnerability Details
Following is the constructor of RAACReleaseOrchestrator contract
constructor(address _raacToken) {
if (_raacToken == address(0)) revert InvalidAddress();
raacToken = IRAACToken(_raacToken);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ORCHESTRATOR_ROLE, msg.sender);
_grantRole(EMERGENCY_ROLE, msg.sender);
categoryAllocations[TEAM_CATEGORY] = 18_000_000 ether;
categoryAllocations[ADVISOR_CATEGORY] = 10_300_000 ether;
categoryAllocations[TREASURY_CATEGORY] = 5_000_000 ether;
categoryAllocations[PRIVATE_SALE_CATEGORY] = 10_000_000 ether;
categoryAllocations[PUBLIC_SALE_CATEGORY] = 15_000_000 ether;
categoryAllocations[LIQUIDITY_CATEGORY] = 6_800_000 ether;
}
As can be seen there are various allocations based on the categories but there are no raac tokens minted which can cover these whole allocations based on the categories. Due to this whenever a user calls the release function there won't be any funds in the contract to give to the beneficiary making the vesting functionality useless
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);
}
Impact
Renders the contract useless
Tools Used
Recommendations
Initally mint raac tokens according to rach category demand.