Core Contracts

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

Attacker Can Trick System to Mint RAAC Tokens Faster Than Intended since tick can be called by anyone

Summary

In the StabilityPool and RAACMinter contracts, someone can cheat the system to make it mint RAAC tokens faster than it should. By withdrawing and redepositing tokens, an attacker can trick the system into thinking it’s being used more than it really is, speeding up the creation of new RAAC tokens up to a maximum of 2000 RAAC per day.

Vulnerability Details

The problem starts with how the system decides how many RAAC tokens to mint. It looks at a number called the "utilization rate," which shows how much of the deposited tokens are being borrowed. If this rate is high, the system mints more RAAC tokens to reward people who deposit. The issue is that an attacker can fake a high utilization rate by playing with their deposits.

The utilization rate is calculated in the RAACMinter contract like this

function getUtilizationRate() internal view returns (uint256) {
uint256 totalBorrowed = lendingPool.getNormalizedDebt();
uint256 totalDeposits = stabilityPool.getTotalDeposits();
if (totalDeposits == 0) return 0;
return (totalBorrowed * 100) / totalDeposits;
}

totalBorrowed is how much is borrowed from the system and totalDeposits is how much is deposited in the StabilityPool.

If totalDeposits goes down if someone withdraws, the utilization rate goes up because the same amount of borrowing looks bigger compared to fewer deposits.


When someone withdraws their rToken from the StabilityPool using the withdraw function:

solidity

function withdraw(uint256 deCRVUSDAmount) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
_update();
// ... burns deToken and sends rToken back to user ...
userDeposits[msg.sender] -= rcrvUSDAmount;
// ... rest of the code ...
}
  • Their deposit (userDeposits[msg.sender]) decreases.

  • This lowers totalDeposits (tracked by rToken.balanceOf(address(this)) in getTotalDeposits()).

  • With totalBorrowed staying the same, the utilization rate spikes.


Since anyone can call the tick() function in RAACMinter:

function tick() external nonReentrant whenNotPaused {
if (emissionUpdateInterval == 0 || block.timestamp >= lastEmissionUpdateTimestamp + emissionUpdateInterval) {
updateEmissionRate();
}
// ... mints RAAC based on blocks passed ...
}
  • If a day has passed (default emissionUpdateInterval is 1 day), it calls updateEmissionRate(). This checks the utilization rate and adjusts the emissionRate

    function calculateNewEmissionRate() internal view returns (uint256) {
    uint256 utilizationRate = getUtilizationRate();
    uint256 adjustment = (emissionRate * adjustmentFactor) / 100;
    if (utilizationRate > utilizationTarget) {
    uint256 increasedRate = emissionRate + adjustment;
    return increasedRate < maxEmissionRate ? increasedRate : maxEmissionRate;
    }
    // ... rest of the logic ...
    }

    With a high utilization rate (from the withdrawal), the emissionRate increases by 5% (default adjustmentFactor).


The attacker then redeposits their rToken using deposit:

function deposit(uint256 amount) external nonReentrant whenNotPaused validAmount(amount) {
_update();
rToken.safeTransferFrom(msg.sender, address(this), amount);
// ... mints deToken to user ...
userDeposits[msg.sender] += amount;
// ... rest of the code ...
}
  • This brings totalDeposits back to normal, but the higher emissionRate stays until the next update.


Repeating the Trick

  • Every day, the attacker withdraws, waits a day, calls tick(), and redeposits.

  • Each time, the emissionRate goes up by 5%, speeding it toward the max of 2000 RAAC/day.

  • Normally, the emissionRate starts at 1000 RAAC/day and adjusts slowly based on real borrowing and depositing.

  • The attacker forces it to think the system is super busy (high utilization), making it jump to 2000 RAAC/day in about 14 days instead of naturally over a longer time.

Impact

  1. The system could mint up to 2000 RAAC/day sooner than planned, adding extra tokens to the supply (e.g., 1000 extra RAAC/day compared to normal).

  2. The attacker (and others with deposits) gets more RAAC rewards than they should, especially if they time it right.

Tools Used

Manual Review

Recommendations

  1. Make emissionRate changes based on utilization over a few days, not just one moment. This way, a quick withdrawal won’t trick it.

  2. Change tick() so only the StabilityPool or a special helper can call it, not just anyone. This stops attackers from timing it perfectly.

Updates

Lead Judging Commences

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

RAACMinter vulnerable to manipulation via flash borrowing to artificially inflate emission rates by temporarily spiking utilization

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

RAACMinter vulnerable to manipulation via flash borrowing to artificially inflate emission rates by temporarily spiking utilization

Support

FAQs

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

Give us feedback!