Core Contracts

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

Since the function `RaacMinter:tick` add excessTokens but this tokens are minted to the `stabilityPool`, If excess tokens are not zero, `RaacMinter:mintRewards` function will always revert with `ERC20 Insufficient Balance`

Description:
The function `RaacMinter:tick` increments the excessTokens count. This tokens will be discounted from the total to mint in the `RaacMinter:mintRewards` and transfered to the reciver. The proble is that the funcion `tick` do not mint the tokens in the `RaacMinter`, it's minting it in the `StabilityPool` and they are never transfered to the `RaacMinter`.
Impact:
If there are excees Tokens, the function `RaacMinter:mintRewards` will always revert with `ERC20 Insufficient Balance`, because tokens are owner by the `StabilityPool`.
Proof of Concept:
**Here are the steps to run the Foundry PoC:**
<details><sumarry>Proof of Code</summary>
1. Open the `linux terminal`, `wsl` in windows.
2. `nomicfoundation` installation:
- If you have `npm` installed run this command:
- `npm install --save-dev @nomicfoundation/hardhat-foundry`
- If you have `yarn` installed run this command:
- `yarn add --dev @nomicfoundation/hardhat-foundry`
- If you have `pnpm` installed run this command:
- `pnpm add --save-dev @nomicfoundation/hardhat-foundry`
3. open the `hardhat.config.cjs`
- Paste this at the begining of the code:
- `require("@nomicfoundation/hardhat-foundry");`
4. run `npx hardhat init-foundry`
- This task will create a `foundry.toml` file with the right configuration and install `forge-std`
5. In the `test/` forlder create a new folder called `ProofOfCodes`
6. In this `test/ProofOfCodes` folder create a new file and paste the following code
7. To run the test you should run `forge test --mt test_exessTokenBalanceIsAlwaysZeroAndUserWontReciveThem -vvvv`
<details><summary>NOTE</summary>
Just for the sake of simplifying the test, I paste this function in the RaacMinter, which is doing exactly the same thing as the tick function by minting tokens and adding excess tokens.
```solidity
function getSomeExessBalance(uint256 amountToMint) external {
excessTokens += amountToMint;
lastUpdateBlock = block.number;
raacToken.mint(address(stabilityPool), amountToMint);
}
```
add this function to the end of the contract.
</details>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test,console2} from "lib/forge-std/src/Test.sol";
import {DebtToken} from "contracts/core/tokens/DebtToken.sol";
import {LendingPool} from "contracts/core/pools/LendingPool/LendingPool.sol";
import {StabilityPool} from "contracts/core/pools/StabilityPool/StabilityPool.sol";
import {RAACMinter} from "contracts/core/minters/RAACMinter/RAACMinter.sol";
import {RAACToken} from "contracts/core/tokens/RAACToken.sol";
import {RToken} from "contracts/core/tokens/RToken.sol";
import {RAACNFT} from "contracts/core/tokens/RAACNFT.sol";
import {RAACHousePrices} from "contracts/core/primitives/RAACHousePrices.sol";
import {ERC20Mock, ERC20} from "contracts/mocks/core/tokens/ERC20Mock.sol";
contract RAACMinterPoC is Test {
StabilityPool stabilityPool;
RAACMinter raacMinter;
RAACToken raacToken;
ERC20Mock crvUsdMock;
RToken rToken;
RAACHousePrices housePrices;
RAACNFT raacNft;
LendingPool reservePool;
DebtToken debtToken;
address initialOwner = makeAddr("initalOwner");
address reciver = makeAddr("reciver");
function setUp() external {
vm.roll(block.number + 100);
vm.warp(block.timestamp + 10 days);
crvUsdMock = new ERC20Mock("crv", "crv");
housePrices = new RAACHousePrices(initialOwner);
raacNft = new RAACNFT(address(crvUsdMock), address(housePrices), initialOwner);
debtToken = new DebtToken("DebtToken", "DT", initialOwner);
rToken = new RToken("RToken", "RT", initialOwner, address(crvUsdMock));
reservePool = new LendingPool(address(crvUsdMock), address(rToken), address(debtToken), address(raacNft), address(housePrices), 1);
stabilityPool = new StabilityPool(initialOwner);
raacToken = new RAACToken(initialOwner, 0, 0);
raacMinter = new RAACMinter(address(raacToken), address(stabilityPool), address(reservePool), initialOwner);
vm.startPrank(initialOwner);
raacToken.setMinter(address(raacMinter));
raacMinter.setStabilityPool(address(stabilityPool));
vm.stopPrank();
}
function test_exessTokenBalanceIsAlwaysZeroAndUserWontReciveThem() external {
vm.roll(block.number + 10);
vm.warp(block.timestamp + 1 days);
raacMinter.getSomeExessBalance(1e18);
assert(raacMinter.getExcessTokens() > 0);
vm.prank(address(stabilityPool));
vm.expectRevert();
raacMinter.mintRewards(reciver, 10e18);
}
}
```
</details>
Recommended Mitigation:
1. Delete the excess tokens functionality and mint always the amount to mint.
2. Mint the tokens to the RAACMinter and update StabilityPool logic.
3. Make some mintRewards function in the stability pool where call this funcion and approve the excess balance.
Updates

Lead Judging Commences

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

RAACMinter wrong excessTokens accounting in tick function

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

RAACMinter wrong excessTokens accounting in tick function

Support

FAQs

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