Core Contracts

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

Double accounting in RAACMinter.tick() leads to unintended token inflation

Relevant GitHub Links

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

Summary

The tick() function in RAACMinter.sol double-accounts minted tokens by both adding them to excessTokens and minting them to the stability pool, effectively doubling the intended token supply.

Vulnerability Details

The tick() function calculates token emissions based on blocks elapsed and emission rate, but then incorrectly handles the minting:

function tick() external nonReentrant whenNotPaused {
// [...]
if (blocksSinceLastUpdate > 0) {
uint256 amountToMint = emissionRate * blocksSinceLastUpdate;
if (amountToMint > 0) {
excessTokens += amountToMint; // @audit First accounting
lastUpdateBlock = currentBlock;
raacToken.mint(address(stabilityPool), amountToMint); // @audit Second accounting
emit RAACMinted(amountToMint);
}
}
}

When tokens are minted:

  1. amountToMint is added to excessTokens for future distribution

  2. The same amountToMint is immediately minted to the stability pool

  3. This creates 2x the intended token supply

Simple PoC:

// Initial state
excessTokens = 0
emissionRate = 100
blocksSinceLastUpdate = 10
// After tick()
amountToMint = 100 * 10 = 1000
excessTokens = 1000 // First 1000 tokens
stabilityPool balance = 1000 // Second 1000 tokens
// Total: 2000 tokens instead of intended 1000

Impact

  • Doubles the effective emission rate of RAAC tokens

  • Creates unintended token inflation

  • Dilutes value for all token holders

  • Disrupts protocol's monetary policy and tokenomics

  • Affects core protocol mechanism

Tools Used

  • Manual Review

Recommendations

Keep only one accounting method. Either:

// Option 1: Only mint to StabilityPool
if (amountToMint > 0) {
lastUpdateBlock = currentBlock;
raacToken.mint(address(stabilityPool), amountToMint);
emit RAACMinted(amountToMint);
}
// OR Option 2: Only track in excessTokens
if (amountToMint > 0) {
excessTokens += amountToMint;
lastUpdateBlock = currentBlock;
emit RAACMinted(amountToMint);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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