Core Contracts

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

Incorrect Emergency Token Transfer in `RAACReleaseOrchestrator`

Summary

The emergencyRevoke function in the RAACReleaseOrchestrator contract incorrectly attempts to transfer unreleased tokens to the contract’s own address (address(this)) instead of the beneficiary. This redundant transfer is ineffective since the tokens are already held by the contract and may lead to transfer failures if the contract’s balance is insufficient, thereby preventing proper token recovery.

Vulnerability Details

In the emergencyRevoke function, after calculating the unreleased tokens from a vesting schedule, the contract deletes the schedule and then executes the following logic:

if (unreleasedAmount > 0) {
raacToken.transfer(address(this), unreleasedAmount);
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
  • Issue:
    The function transfers unreleased tokens to address(this), which is the contract itself. This is redundant because:

    • The tokens are already held in the contract.

    • If the contract’s token balance is insufficient (due to previous transfers or other reasons), the transfer will fail.

  • Expected Behavior:
    The unreleased tokens should be transferred to the beneficiary or an appropriate recovery address to ensure that the tokens are effectively recovered in an emergency scenario.

Proof-of-Concept (POC)

  1. Initial Conditions:

    • A vesting schedule is created for a beneficiary with:

      • totalAmount = 100e18 tokens.

      • releasedAmount = 40e18 tokens.

    • The calculated unreleased amount is:

      unreleasedAmount = totalAmount - releasedAmount = 100e18 - 40e18 = 60e18 tokens.
  2. Execution in emergencyRevoke:

    • The function deletes the vesting schedule.

    • It then attempts to transfer 60e18 tokens to address(this):

      raacToken.transfer(address(this), 60e18);
    • Since the tokens are already held by the contract, this transfer is redundant. Moreover, if the contract does not have an adequate balance (perhaps due to previous distributions), the transfer will fail.

  3. Outcome:

    • The emergency revoke process fails to properly recover and reassign the unreleased tokens, potentially leaving stakeholders without access to their due tokens during emergencies.

Impact

  • The erroneous transfer prevents the intended recovery of unreleased tokens in emergency scenarios.

Tools Used

Manual Review

Recommendations

Change the transfer destination in the emergencyRevoke function from address(this) to the beneficiary, e.g., replace:

raacToken.transfer(address(this), unreleasedAmount);

with

raacToken.transfer(beneficiary, unreleasedAmount);
Updates

Lead Judging Commences

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