// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Script, console} from "forge-std/Script.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC3156FlashBorrower} from "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol"; import {SimpleERC3156FlashVault} from "../../contracts/flash/SimpleERC3156FlashVault.sol"; import {MinimalERC3156FlashBorrower} from "../../contracts/flash/MinimalERC3156FlashBorrower.sol"; /** * @title TestOneUSDTFlash * @notice Live / fork: deploy minimal borrower, pre-fund fee, execute 1 USDT flash against an existing vault. * * Env: * PRIVATE_KEY — deployer (pays gas; seeds fee to borrower) * FLASH_VAULT — deployed SimpleERC3156FlashVault * FLASH_VAULT_TOKEN — optional; default official USDT Chain 138 * FLASH_TEST_AMOUNT — optional raw amount (default 1e6 = 1 USDT with 6 decimals) * * Usage: * forge script script/flash/TestOneUSDTFlash.s.sol:TestOneUSDTFlash --rpc-url $RPC_URL_138 --broadcast -vvvv */ contract TestOneUSDTFlash is Script { address internal constant DEFAULT_USDT_138 = 0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1; function run() external { uint256 pk = vm.envUint("PRIVATE_KEY"); address deployer = vm.addr(pk); address vaultAddr = vm.envAddress("FLASH_VAULT"); address token = vm.envOr("FLASH_VAULT_TOKEN", DEFAULT_USDT_138); uint256 amount = vm.envOr("FLASH_TEST_AMOUNT", uint256(1_000_000)); // 1 USDT (6 dp) SimpleERC3156FlashVault vault = SimpleERC3156FlashVault(vaultAddr); require(!vault.borrowerAllowlistEnabled() || vault.owner() == deployer, "allowlist on: deployer must be vault owner"); uint256 fee = vault.previewFlashFee(token, amount); uint256 vaultBal = IERC20(token).balanceOf(vaultAddr); console.log("Deployer:", deployer); console.log("Vault:", vaultAddr); console.log("Token:", token); console.log("Amount (raw):", amount); console.log("Fee (raw):", fee); console.log("Vault token balance (raw):", vaultBal); require(vaultBal >= amount, "vault liquidity < amount"); vm.startBroadcast(pk); MinimalERC3156FlashBorrower borrower = new MinimalERC3156FlashBorrower(vaultAddr); console.log("MinimalERC3156FlashBorrower:", address(borrower)); if (vault.borrowerAllowlistEnabled()) { vault.setBorrowerApproved(address(borrower), true); } // Callback must return amount+fee; vault only credits `amount` before callback — need `fee` pre-funded on borrower. IERC20(token).transfer(address(borrower), fee); vault.flashLoan(IERC3156FlashBorrower(address(borrower)), token, amount, ""); vm.stopBroadcast(); console.log("Done. Vault balance after (raw):", IERC20(token).balanceOf(vaultAddr)); } }