// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../contracts/rwa/RWAToken.sol"; import "../../contracts/rwa/LiIndexFlashVault.sol"; import {IERC3156FlashBorrower} from "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract MockFlashBorrower is IERC3156FlashBorrower { bytes32 private constant _RETURN = keccak256("ERC3156FlashBorrower.onFlashLoan"); function onFlashLoan( address, address token, uint256 amount, uint256 fee, bytes calldata ) external returns (bytes32) { IERC20(token).approve(msg.sender, amount + fee); return _RETURN; } } contract LiIndexFlashVaultTest is Test { LiIndexFlashVault vault; RWAToken liToken; MockFlashBorrower borrower; address admin = address(0xA11CE); function setUp() public { vm.startPrank(admin); liToken = new RWAToken( "LiXAU Test", "LiXAU", 6, "LiXAU", "Commodity", "Gold", "Index", "XAU", "M00", admin, admin, admin, 1_000_000, 0, keccak256("methodology-test") ); vault = new LiIndexFlashVault( admin, 8000, 5000, 5, 250, 86400, 2400_00000000 ); vault.setSupportedToken(address(liToken), true); borrower = new MockFlashBorrower(); liToken.mint(admin, 1_000_000e6); liToken.approve(address(vault), type(uint256).max); vault.deposit(address(liToken), 500_000e6); vm.stopPrank(); } function test_MaxFlashLoanWithinLtv() public view { uint256 max = vault.maxFlashLoan(address(liToken)); assertEq(max, 250_000e6); } function test_FlashLoanRepays() public { vm.prank(admin); vault.flashLoan(IERC3156FlashBorrower(address(borrower)), address(liToken), 100_000e6, ""); assertEq(vault.outstandingFlash(address(liToken)), 0); } function test_BlocksWhenUtilizationExceeded() public { vm.startPrank(admin); vault.flashLoan(IERC3156FlashBorrower(address(borrower)), address(liToken), 400_000e6, ""); vm.stopPrank(); assertEq(vault.maxFlashLoan(address(liToken)), 0); } }