Minting of RAAC token can be triggered within certain intervals through tick which mints to the stability pool according to the emission rate and updates the excessTokens
held by the contract.
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/minters/RAACMinter/RAACMinter.sol#L271
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);
}
}
}
The issue is that the token is minted to stabilityPool
but excessTokens
counter assumes the token is held by the contract itself.
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/minters/RAACMinter/RAACMinter.sol#L191
function mintRewards(address to, uint256 amount) external nonReentrant whenNotPaused {
if (msg.sender != address(stabilityPool)) revert OnlyStabilityPool();
@> uint256 toMint = excessTokens >= amount ? 0 : amount - excessTokens;
excessTokens = excessTokens >= amount ? excessTokens - amount : 0;
if (toMint > 0) {
@> raacToken.mint(address(this), toMint);
}
@> raacToken.safeTransfer(to, amount);
emit RAACMinted(amount);
}
when mintRewards
is invoked it check if the contract has enough amount(excessTokens
) if not it mints
additional token to add up but the excessToken
is not held by the contract itself making the call to safeTransfer
to revert.
Impact
MintRewards would revert due to inconsistent state
Recommendation
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);
+ raacToken.mint(address(this), amountToMint);
emit RAACMinted(amountToMint);
}
}
}