pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.sol";
import {LendingPool} from "contracts/core/pools/LendingPool/LendingPool.sol";
import {crvUSDToken} from "contracts/mocks/core/tokens/crvUSDToken.sol";
import {RToken} from "contracts/core/tokens/RToken.sol";
import {DebtToken} from "contracts/core/tokens/DebtToken.sol";
import {RAACNFT} from "contracts/core/tokens/RAACNFT.sol";
import {RAACHousePricesMock} from "contracts/mocks/core/primitives/RAACHousePricesMock.sol";
import {RAACHousePriceOracle} from "contracts/core/oracles/RAACHousePriceOracle.sol";
import {MockFunctionsRouter} from "contracts/mocks/core/oracles/MockFunctionsRouter.sol";
import {FeeCollector} from "contracts/core/collectors/FeeCollector.sol";
import {MockVeToken} from "contracts/mocks/core/tokens/MockVeToken.sol";
contract SetupContract is Test {
address public user1;
address public user2;
address public user3;
address public treasury;
address public repairFund;
LendingPool public lendingPool;
crvUSDToken public _crvUSDToken;
RToken public rToken;
MockVeToken public veRToken;
DebtToken public debtToken;
RAACHousePricesMock public raacHousePrices;
RAACNFT public raacNFT;
RAACHousePriceOracle public raacHousePriceOracle;
FeeCollector public feeCollector;
uint256 public constant INITIAL_PRIME_RATE = 1e26;
function setUp() external {
user1 = makeAddr("user1");
user2 = makeAddr("user2");
user3 = makeAddr("user3");
treasury = makeAddr("treasury");
repairFund = makeAddr("repairFund");
veRToken = new MockVeToken();
_crvUSDToken = new crvUSDToken(address(this));
rToken = new RToken("rtoken", "rtk", address(this), address(_crvUSDToken));
debtToken = new DebtToken("debtToken", "dtk", address(this));
raacHousePrices = new RAACHousePricesMock();
raacNFT = new RAACNFT(address(_crvUSDToken), address(raacHousePrices), address(this));
raacHousePriceOracle = new RAACHousePriceOracle(
address(new MockFunctionsRouter()), bytes32(bytes("fun-ethereum-mainnet-1")), address(this)
);
feeCollector = new FeeCollector(address(rToken), address(veRToken), treasury, repairFund, address(this));
lendingPool = new LendingPool(
address(_crvUSDToken),
address(rToken),
address(debtToken),
address(raacNFT),
address(raacHousePrices),
INITIAL_PRIME_RATE
);
rToken.setReservePool(address(lendingPool));
debtToken.setReservePool(address(lendingPool));
_crvUSDToken.mint(user1, 10000e18);
_crvUSDToken.mint(user2, 100e18);
_crvUSDToken.mint(user3, 100e18);
}
function testFeeCollector() public {
vm.startPrank(user1);
_crvUSDToken.approve(address(lendingPool), 1000e18);
lendingPool.deposit(1000e18);
rToken.approve(address(feeCollector), 1000e18);
feeCollector.collectFee(1000e18, 1);
vm.stopPrank();
veRToken.mint(user2, 50);
veRToken.mint(user3, 50);
feeCollector.distributeCollectedFees();
console.log("Balance before 1st claim: ", rToken.balanceOf(user2));
feeCollector.claimRewards(user2);
console.log("Balance after 1st claim: ", rToken.balanceOf(user2));
vm.startPrank(user1);
_crvUSDToken.approve(address(lendingPool), 1000e18);
lendingPool.deposit(1000e18);
rToken.approve(address(feeCollector), 1000e18);
feeCollector.collectFee(1000e18, 1);
vm.stopPrank();
vm.warp(block.timestamp + 8 days);
feeCollector.distributeCollectedFees();
feeCollector.claimRewards(user2);
console.log("Balance after 2st claim: ", rToken.balanceOf(user2));
}
}
Here’s an example of what happens (values are not real, as not all fees go to users with voting power). In the POC, only 70% of lending fees (id:1) go to veRaac holders. But for simplicity, let's assume all fees go to veRaac holders in this example.