The amount transferred will differ from what the user expects.
pragma solidity ^0.8.19;
import "../../contracts/core/pools/LendingPool/LendingPool.sol";
import "../../contracts/libraries/pools/ReserveLibrary.sol";
import "../../lib/forge-std/src/Test.sol";
import "../../lib/forge-std/src/console.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../../contracts/core/tokens/DebtToken.sol";
import "../../contracts/core/tokens/RToken.sol";
import "../../contracts/core/tokens/RAACNFT.sol";
import "../../contracts/core/primitives/RAACHousePrices.sol";
contract MockERC20 is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
function balanceOf(address account) public view override returns (uint256) {
return super.balanceOf(account);
}
}
contract ReserveLibraryTest is Test {
address owner;
address user;
LendingPool lendingPool;
MockERC20 reserveAsset;
RToken rToken;
DebtToken debtToken;
RAACNFT raacNFt;
address priceOracle;
RAACHousePrices housePrices;
ReserveLibrary.ReserveData reserve;
ReserveLibrary.ReserveRateData rateData;
function setUp() public {
owner = makeAddr("owner");
initializeContracts(owner);
configureContracts(owner);
user = makeAddr("user");
}
function initializeContracts(address _owner) internal {
reserveAsset = new MockERC20("reserveMock", "mkTkn");
rToken = new RToken("rMock", "mkTkn", _owner, address(reserveAsset));
debtToken = new DebtToken("debtMock", "mkTkn", _owner);
priceOracle = makeAddr("priceOracle");
housePrices = new RAACHousePrices(_owner);
raacNFt = new RAACNFT(address(reserveAsset), address(housePrices), _owner);
lendingPool = new LendingPool(
address(reserveAsset), address(rToken), address(debtToken), address(raacNFt), address(housePrices), 1e26
);
}
function configureContracts(address _owner) internal {
vm.startPrank(_owner);
housePrices.setOracle(priceOracle);
debtToken.setReservePool(address(lendingPool));
rToken.setReservePool(address(lendingPool));
vm.stopPrank();
vm.prank(priceOracle);
housePrices.setHousePrice(1, 10_000);
}
function updateReserveStates() public {
(
address reserveRTokenAddress,
address reserveAssetAddress,
address reserveDebtTokenAddress,
uint256 totalLiquidity,
uint256 totalUsage,
uint128 liquidityIndex,
uint128 usageIndex,
uint40 lastUpdateTimestamp
) = lendingPool.reserve();
reserve = ReserveLibrary.ReserveData(
reserveRTokenAddress,
reserveAssetAddress,
reserveDebtTokenAddress,
totalLiquidity,
totalUsage,
liquidityIndex,
usageIndex,
lastUpdateTimestamp
);
(
uint256 currentLiquidityRate,
uint256 currentUsageRate,
uint256 primeRate,
uint256 baseRate,
uint256 optimalRate,
uint256 maxRate,
uint256 optimalUtilizationRate,
uint256 protocolFeeRate
) = lendingPool.rateData();
rateData = ReserveLibrary.ReserveRateData(
currentLiquidityRate,
currentUsageRate,
primeRate,
baseRate,
optimalRate,
maxRate,
optimalUtilizationRate,
protocolFeeRate
);
}
function testRTokenTransferTransfersWrongAmount() public {
address borrower = makeAddr("borrower");
address recipient = makeAddr("recipient");
reserveAsset.mint(user, 10_000_000);
reserveAsset.mint(borrower, 10_000);
vm.startPrank(user);
deposit(1000);
vm.stopPrank();
vm.startPrank(borrower);
mintNFT();
depositNFT();
lendingPool.borrow(1000);
vm.stopPrank();
skip(12);
vm.startPrank(user);
deposit(9_999_000);
vm.stopPrank();
skip(12);
updateReserveStates();
ReserveLibrary.updateReserveInterests(reserve, rateData);
uint256 amountToTransfer = 10_000_000;
vm.startPrank(user);
rToken.transfer(recipient, amountToTransfer);
vm.stopPrank();
assertNotEq(amountToTransfer, rToken.balanceOf(recipient));
console.log("sender balance after transfer: %d", rToken.balanceOf(user));
console.log("recipient balance after transfer: %d", rToken.balanceOf(recipient));
}
function mintNFT() internal {
reserveAsset.approve(address(raacNFt), 10_000);
raacNFt.mint(1, 10_000);
}
function depositNFT() internal {
raacNFt.approve(address(lendingPool), 1);
lendingPool.depositNFT(1);
}
function deposit(uint256 amount) internal {
reserveAsset.approve(address(lendingPool), amount);
lendingPool.deposit(amount);
}
}