Core Contracts

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

Single Minter Restriction Prevents Concurrent Minting for RAACMinter and RAACReleaseOrchestrator

Summary

The RAACToken contract allows minting only from a single authorized address. RAACMinter uses its tick() function to mint rewards for the stabilityPool, while RAACReleaseOrchestrator must release vested tokens for beneficiaries. Both modules are designed to operate concurrently; however, the current implementation forces only one module to have minting authority, causing RAACReleaseOrchestrator’s actions—such as emergencyRevoke()—to fail when RAACMinter is set as minter in RaacToken.

Vulnerability Details

The RAAC token contract enforces minting with a single minter variable and the following modifier:

modifier onlyMinter() {
if (msg.sender != minter) revert OnlyMinterCanMint();
_;
}

The setter function is defined as:

function setMinter(address _minter) external onlyOwner {
if (_minter == address(0)) revert InvalidAddress();
minter = _minter;
emit MinterSet(_minter);
}

This authorizes only one contract to mint tokens at any given time. For instance, RAACMinter’s tick() function mints rewards to the stability pool:

function tick() external nonReentrant whenNotPaused {
if (emissionUpdateInterval == 0 || block.timestamp >= lastEmissionUpdateTimestamp + emissionUpdateInterval) {
updateEmissionRate();
}
uint256 currentBlock = block.number;
uint256 blocksSinceLastUpdate = currentBlock - lastUpdateBlock;
if (blocksSinceLastUpdate > 0) {
uint256 amountToMint = emissionRate * blocksSinceLastUpdate;
if (amountToMint > 0) {
excessTokens += amountToMint;
lastUpdateBlock = currentBlock;
raacToken.mint(address(stabilityPool), amountToMint);
emit RAACMinted(amountToMint);
}
}
}

Conversely, RAACReleaseOrchestrator’s emergencyRevoke() function (which may require minting in a vesting release scenario) would attempt to use the RAAC token contract as follows:

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) {
raacToken.transfer(address(this), unreleasedAmount);
emit EmergencyWithdraw(beneficiary, unreleasedAmount);
}
emit VestingScheduleRevoked(beneficiary);
}

Since the RAAC token contract allows minting only from one minter, if RAACMinter is set as the minter, any vesting-related minting (like emergencyRevoke()) call by RAACReleaseOrchestrator will revert with OnlyMinterCanMint().

Impact

The oversights results in RAACMinter’s tick() function successfully minting rewards to the stability pool while completely blocking vesting releases managed by RAACReleaseOrchestrator. This directly causes vesting schedules to stall, denying beneficiaries their scheduled token releases and potentially resulting in a denial-of-service condition for vesting functions.

Tools Used

Manual Review

Recommendations

Update the RAAC token contract to support multiple authorized minters using a role-based access control mechanism. For example, replace the single minter variable with a mapping and modify the minting check:

- address public minter;
+ mapping(address => bool) public minters;
- modifier onlyMinter() {
- if (msg.sender != minter) revert OnlyMinterCanMint();
- _;
- }
+ modifier onlyMinter() {
+ if (!minters[msg.sender]) revert OnlyMinterCanMint();
+ _;
+ }

And update the setter function:

- function setMinter(address _minter) external onlyOwner {
- if (_minter == address(0)) revert InvalidAddress();
- minter = _minter;
- emit MinterSet(_minter);
- }
+ function setMinter(address _minter, bool _status) external onlyOwner {
+ if (_minter == address(0)) revert InvalidAddress();
+ minters[_minter] = _status;
+ emit MinterSet(_minter, _status);
+ }

This change allows both RAACMinter and RAACReleaseOrchestrator to have minting rights concurrently, ensuring that both reward distribution and vesting token releases occur without conflict

Updates

Lead Judging Commences

inallhonesty Lead Judge
4 months ago
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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