Core Contracts

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

RAACMinter: Unauthorized Stability Pool Updates

Summary

The RAACMinter contract allows an account with UPDATER_ROLE to arbitrarily change the stabilityPool address without proper validation or governance oversight. This enables an attacker to replace the Stability Pool with a malicious contract, bypassing protocol safeguards and minting unlimited RAAC tokens. This flaw violates the principle of least privilege and introduces a single point of failure.

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/minters/RAACMinter/RAACMinter.sol#L124

Vulnerability Details

An malicious actor gains the update role

Set Malicious Stability Pool: Call setStabilityPool() with the address of a malicious contract.

Mint Unlimited RAAC: The malicious Stability Pool triggers mintRewards(), minting RAAC tokens without validation.

Code Proof:

In RAACMinter.sol, the UPDATER_ROLE can freely update the Stability Pool:

function setStabilityPool(address _stabilityPool) external onlyRole(UPDATER_ROLE) {
stabilityPool = IStabilityPool(_stabilityPool); // No validation or delay
}

Attack Simulation:

Malicious actor deploys a fake Stability Pool contract:

contract FakeStabilityPool {
function getTotalDeposits() external pure returns (uint256) {
return 1_000_000e18; // Fake high deposits to maximize minting
}
}

Actor calls:

// Set malicious pool
RAACMinter.setStabilityPool(address(FakeStabilityPool));

Actor triggers mintRewards():

// Mint RAAC tokens against fake deposits
RAACMinter.mintRewards(attackerAddress, 1_000_000e18);

Result: RAAC tokens are minted without collateral, causing hyperinflation.

Impact

Token Hyperinflation: Unlimited RAAC minting devalues the token, rendering it worthless.

Fund Drainage: Malicious Stability Pool can siphon funds from other protocol components.

Protocol Collapse: Loss of user trust and financial insolvency.

Tools Used

Manual Review, static analysis

Recommendations

Restrict Stability Pool updates to governance proposals with a timelock and validation.

Step 1: Restrict Updates to Governance

// RAACMinter.sol
function setStabilityPool(address _stabilityPool) external onlyRole(GOVERNANCE_ROLE) { // Require governance role
require(_stabilityPool != address(0), "Invalid address");
require(_stabilityPool.code.length > 0, "Not a contract"); // Validate contract
stabilityPool = IStabilityPool(_stabilityPool);
emit StabilityPoolUpdated(_stabilityPool);
}

Step 2: Add Timelock for Critical Changes
Integrate with TimelockController to enforce delays:

// RAACMinter.sol
ITimelockController public timelock;
function setStabilityPool(address _stabilityPool) external {
require(msg.sender == address(timelock), "Caller must be timelock");
stabilityPool = IStabilityPool(_stabilityPool);
}

Step 3: Governance Proposal Workflow

Governance proposes a new Stability Pool address.

Proposal passes after a 7-day timelock.

TimelockController executes the update.

Why This Fix Works

Governance Control: Only approved governance proposals can update the Stability Pool.

Contract Validation: Ensures the new address is a valid smart contract.

Timelock: Provides users time to audit changes and exit if malicious.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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