Files
smom-dbis-138/test/flash/SwapFlashWorkflowBorrower.t.sol
defiQUG 76aa419320 feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault.
- Token-aggregation service routes, planner, chain config, relay env templates.
- Config snapshots and multi-chain deployment markdown updates.
- gitignore services/btc-intake/dist/ (tsc output); do not track dist.

Run forge build && forge test before deploy (large solc graph).

Made-with: Cursor
2026-04-07 23:40:52 -07:00

88 lines
3.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.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 {SwapFlashWorkflowBorrower, IDODOStyleSwapExactIn} from "../../contracts/flash/SwapFlashWorkflowBorrower.sol";
/// @notice 1:1 swap router for tests (ignores pool).
contract MockSwapRouter1to1 is IDODOStyleSwapExactIn {
ERC20 public immutable tokenA;
ERC20 public immutable tokenB;
constructor(ERC20 a, ERC20 b) {
tokenA = a;
tokenB = b;
}
function swapExactIn(address, address tokenIn, uint256 amountIn, uint256 minAmountOut)
external
override
returns (uint256 amountOut)
{
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
address tokenOut = tokenIn == address(tokenA) ? address(tokenB) : address(tokenA);
amountOut = amountIn;
require(amountOut >= minAmountOut, "min");
IERC20(tokenOut).transfer(msg.sender, amountOut);
}
}
contract MockERC20Mint is ERC20 {
constructor(string memory n, string memory s) ERC20(n, s) {}
function mint(address to, uint256 v) external {
_mint(to, v);
}
}
contract SwapFlashWorkflowBorrowerTest is Test {
SimpleERC3156FlashVault internal vault;
MockERC20Mint internal tokenA;
MockERC20Mint internal tokenB;
MockSwapRouter1to1 internal router;
SwapFlashWorkflowBorrower internal borrower;
address internal owner = address(0xA11);
address internal user = address(0xB22);
function setUp() public {
vm.startPrank(owner);
vault = new SimpleERC3156FlashVault(owner, 5);
tokenA = new MockERC20Mint("A", "A");
tokenB = new MockERC20Mint("B", "B");
tokenA.mint(address(vault), 1_000_000e18);
vault.setTokenSupported(address(tokenA), true);
vm.stopPrank();
router = new MockSwapRouter1to1(tokenA, tokenB);
tokenA.mint(address(router), 10_000_000e18);
tokenB.mint(address(router), 10_000_000e18);
borrower = new SwapFlashWorkflowBorrower(address(vault));
}
function test_roundTripSwap_prefundFeeInBorrowedToken() public {
uint256 amount = 50_000e18;
uint256 fee = vault.flashFee(address(tokenA), amount);
tokenA.mint(address(borrower), fee);
SwapFlashWorkflowBorrower.SwapFlashParams memory p = SwapFlashWorkflowBorrower.SwapFlashParams({
integration: address(router),
pool: address(0xdead),
midToken: address(tokenB),
minOutFirst: amount,
minOutSecond: amount
});
bytes memory data = abi.encode(p);
vm.prank(user);
vault.flashLoan(IERC3156FlashBorrower(address(borrower)), address(tokenA), amount, data);
assertEq(vault.totalFeesCollected(address(tokenA)), fee);
}
}