Core Contracts

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

Incorrect address transfer of unreleased amount of tokens in Release Orchestrator in case of a emergency

Summary

In the situation when we call the emergencyRevoke function of the RAACReleaseOrchestrator contract we should be transfering the unreleasedAmount of RAAC tokens to the passed beneficiary but instead of that we are transfering them back in the same contract.

function emergencyRevoke(address beneficiary) external onlyRole(EMERGENCY_ROLE) {
VestingSchedule storage schedule = vestingSchedules[beneficiary];
if (!schedule.initialized) revert NoVestingSchedule();
uint256 unreleasedAmount = schedule.totalAmount - schedule.releasedAmount;
delete vestingSchedules[beneficiary];
if (unreleasedAmount > 0) {
//@Audit incorrect address to transfer tokens
raacToken.transfer(address(this), unreleasedAmount);
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
emit VestingScheduleRevoked(beneficiary);
}

Vulnerability Details

In case of a emergency withdraw needed for the vested tokens in the RAACReleaseOrchestrator contract we would fail to do so when calling the emergencyRevoke as the tokens are transferred back to the RAACReleaseOrchestrator contract instead of the beneficiary address.

Impact

We can't withdraw the raacTokens from the RAACReleaseOrchestrator contract in case of an emergency, which means if the contract is breached the assets in it cannot be rescued.

Tools Used

  • Manual Review

Recommendations

Change the target of the RAAC tokens transfers to be the beneficiary address:

function emergencyRevoke(address beneficiary) external onlyRole(EMERGENCY_ROLE) {
VestingSchedule storage schedule = vestingSchedules[beneficiary];
if (!schedule.initialized) revert NoVestingSchedule();
uint256 unreleasedAmount = schedule.totalAmount - schedule.releasedAmount;
delete vestingSchedules[beneficiary];
if (unreleasedAmount > 0) {
//@Audit incorrect address to transfer tokens
- raacToken.transfer(address(this), unreleasedAmount);
+ raacToken.transfer(beneficiary, unreleasedAmount);
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
emit VestingScheduleRevoked(beneficiary);
}
Updates

Lead Judging Commences

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

RAACReleaseOrchestrator::emergencyRevoke sends revoked tokens to contract address with no withdrawal mechanism, permanently locking funds

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

RAACReleaseOrchestrator::emergencyRevoke sends revoked tokens to contract address with no withdrawal mechanism, permanently locking funds

Support

FAQs

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

Give us feedback!