Thus, because the rewards calculation returns 0, no RAAC tokens are ever transferred out to users, causing the tokens to be permanently locked in the StabilityPool contract.
pragma solidity ^0.8.19;
import {Test} from "forge-std/Test.sol";
import {console} from "forge-std/console.sol";
import {LendingPool} from "../contracts/core/pools/LendingPool/LendingPool.sol";
import {StabilityPool} from "../contracts/core/pools/StabilityPool/StabilityPool.sol";
import {RAACNFT} from "../contracts/core/tokens/RAACNFT.sol";
import {RAACHousePrices} from "contracts/core/primitives/RAACHousePrices.sol";
import {RToken} from "../contracts/core/tokens/RToken.sol";
import {DebtToken} from "../contracts/core/tokens/DebtToken.sol";
import {crvUSDToken} from "contracts/mocks/core/tokens/crvUSDToken.sol";
import {ILendingPool} from "contracts/interfaces/core/pools/LendingPool/ILendingPool.sol";
import "../contracts/core/tokens/DEToken.sol";
import "../contracts/core/tokens/RAACToken.sol";
import {RAACMinter} from "../contracts/core/minters/RAACMinter/RAACMinter.sol";
contract Audit_Test is Test {
LendingPool public lendingPool;
StabilityPool public stabilityPool;
RAACNFT public raacNFT;
RAACHousePrices public priceOracle;
RToken public rToken;
DebtToken public debtToken;
crvUSDToken public crvusd;
DEToken public deToken;
RAACToken public raacToken;
RAACMinter public raacMinter;
address owner = makeAddr("owner");
uint256 constant INITIAL_PRIME_RATE = 1e27;
function setUp() public {
vm.startPrank(owner);
crvusd = new crvUSDToken(owner);
crvusd.setMinter(owner);
priceOracle = new RAACHousePrices(owner);
priceOracle.setOracle(owner);
raacNFT = new RAACNFT(address(crvusd), address(priceOracle), owner);
rToken = new RToken("RToken", "RT", owner, address(crvusd));
debtToken = new DebtToken("DebtToken", "DT", owner);
deToken = new DEToken("DEToken", "DET", owner, address(rToken));
uint256 initialPrimeRate = 0.1e27;
lendingPool = new LendingPool(
address(crvusd),
address(rToken),
address(debtToken),
address(raacNFT),
address(priceOracle),
initialPrimeRate
);
raacToken = new RAACToken(owner, 1000, 1000);
stabilityPool = new StabilityPool(owner);
raacMinter = new RAACMinter(
address(raacToken),
address(stabilityPool),
address(lendingPool),
owner
);
stabilityPool.initialize(
address(rToken),
address(deToken),
address(raacToken),
address(raacMinter),
address(crvusd),
address(lendingPool)
);
rToken.setReservePool(address(lendingPool));
debtToken.setReservePool(address(lendingPool));
rToken.transferOwnership(address(lendingPool));
debtToken.transferOwnership(address(lendingPool));
deToken.setStabilityPool(address(stabilityPool));
deToken.transferOwnership(address(stabilityPool));
lendingPool.setStabilityPool(address(stabilityPool));
raacToken.setMinter(address(raacMinter));
raacToken.manageWhitelist(address(stabilityPool), true);
vm.stopPrank();
}
function test_POC() public {
uint256 user1Amount = 13187;
uint256 user2Amount = 11594;
address user1 = makeAddr("user1");
address user2 = makeAddr("user2");
vm.startPrank(owner);
crvusd.mint(user1, user1Amount);
crvusd.mint(user2, user2Amount);
vm.stopPrank();
vm.startPrank(user1);
crvusd.approve(address(lendingPool), user1Amount);
lendingPool.deposit(user1Amount);
rToken.approve(address(stabilityPool), user1Amount);
stabilityPool.deposit(user1Amount);
vm.stopPrank();
vm.startPrank(user2);
crvusd.approve(address(lendingPool), user2Amount);
lendingPool.deposit(user2Amount);
rToken.approve(address(stabilityPool), user2Amount);
stabilityPool.deposit(user2Amount);
vm.stopPrank();
vm.warp(block.timestamp + 7 days);
vm.roll(block.number + 1);
raacMinter.updateEmissionRate();
vm.warp(block.timestamp + 1 days);
vm.roll(block.number + 1);
raacMinter.tick();
vm.prank(user1);
stabilityPool.withdraw(user1Amount);
vm.prank(user2);
stabilityPool.withdraw(user2Amount);
assertEq(rToken.balanceOf(user1), user1Amount);
assertEq(rToken.balanceOf(user2), user2Amount);
assertEq(raacToken.balanceOf(user1), 0);
assertEq(raacToken.balanceOf(user2), 0);
assertEq(raacToken.balanceOf(address(stabilityPool)), 306249999999999996);
}
}
Implement a function to withdraw excess tokens from the contract if no rewards are being distributed to the user when deposit is < 1e6