Files
smom-dbis-138/test/bridge/trustless/Chain138PilotDexVenues.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

231 lines
9.4 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test} from "forge-std/Test.sol";
import "../../../contracts/bridge/trustless/EnhancedSwapRouterV2.sol";
import "../../../contracts/bridge/trustless/RouteTypesV2.sol";
import "../../../contracts/bridge/trustless/adapters/UniswapV3RouteExecutorAdapter.sol";
import "../../../contracts/bridge/trustless/adapters/BalancerRouteExecutorAdapter.sol";
import "../../../contracts/bridge/trustless/adapters/CurveRouteExecutorAdapter.sol";
import "../../../contracts/bridge/trustless/adapters/OneInchRouteExecutorAdapter.sol";
import "../../../contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract PilotVenueToken is ERC20 {
constructor(string memory name_, string memory symbol_, uint256 supply) ERC20(name_, symbol_) {
_mint(msg.sender, supply);
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract Chain138PilotDexVenuesTest is Test {
PilotVenueToken internal weth;
PilotVenueToken internal usdt;
PilotVenueToken internal usdc;
PilotVenueToken internal dai;
Chain138PilotUniswapV3Router internal uniswapRouter;
Chain138PilotBalancerVault internal balancerVault;
Chain138PilotCurve3Pool internal curvePool;
Chain138PilotOneInchAggregationRouter internal oneInchRouter;
EnhancedSwapRouterV2 internal router;
address internal user = address(0x1234);
bytes32 internal constant BALANCER_POOL_ID = keccak256("chain138-pilot-balancer-weth-usdc");
function setUp() public {
weth = new PilotVenueToken("Wrapped Ether", "WETH", 10_000 ether);
usdt = new PilotVenueToken("Tether", "USDT", 50_000_000 * 1e6);
usdc = new PilotVenueToken("USD Coin", "USDC", 50_000_000 * 1e6);
dai = new PilotVenueToken("Dai", "DAI", 10_000_000 ether);
uniswapRouter = new Chain138PilotUniswapV3Router();
balancerVault = new Chain138PilotBalancerVault();
curvePool = new Chain138PilotCurve3Pool(address(usdt), address(usdc), address(0), 4);
oneInchRouter = new Chain138PilotOneInchAggregationRouter();
router = new EnhancedSwapRouterV2(address(weth), address(usdt), address(usdc), address(dai));
router.setProviderAdapter(RouteTypesV2.Provider.UniswapV3, address(new UniswapV3RouteExecutorAdapter()));
router.setProviderAdapter(RouteTypesV2.Provider.Balancer, address(new BalancerRouteExecutorAdapter()));
router.setProviderAdapter(RouteTypesV2.Provider.Curve, address(new CurveRouteExecutorAdapter()));
router.setProviderAdapter(RouteTypesV2.Provider.OneInch, address(new OneInchRouteExecutorAdapter()));
router.setProviderEnabled(RouteTypesV2.Provider.OneInch, true);
weth.approve(address(uniswapRouter), type(uint256).max);
usdt.approve(address(uniswapRouter), type(uint256).max);
usdc.approve(address(uniswapRouter), type(uint256).max);
weth.approve(address(balancerVault), type(uint256).max);
usdt.approve(address(balancerVault), type(uint256).max);
usdc.approve(address(balancerVault), type(uint256).max);
usdt.approve(address(curvePool), type(uint256).max);
usdc.approve(address(curvePool), type(uint256).max);
weth.approve(address(oneInchRouter), type(uint256).max);
usdt.approve(address(oneInchRouter), type(uint256).max);
usdc.approve(address(oneInchRouter), type(uint256).max);
uniswapRouter.seedPair(address(weth), address(usdt), 3000, 100 ether, 210_000 * 1e6);
uniswapRouter.seedPair(address(weth), address(usdc), 3000, 100 ether, 210_000 * 1e6);
balancerVault.seedPool(BALANCER_POOL_ID, address(weth), address(usdc), 100 ether, 210_000 * 1e6, 30);
curvePool.fund(500_000 * 1e6, 500_000 * 1e6, 0);
oneInchRouter.seedRoute(address(weth), address(usdt), 100 ether, 210_000 * 1e6, 35);
router.setProviderRoute(
address(weth),
address(usdt),
RouteTypesV2.Provider.UniswapV3,
address(uniswapRouter),
abi.encode(bytes(""), uint24(3000), address(uniswapRouter), false),
true
);
router.setProviderRoute(
address(weth),
address(usdc),
RouteTypesV2.Provider.Balancer,
address(balancerVault),
abi.encode(BALANCER_POOL_ID),
true
);
router.setProviderRoute(
address(usdt),
address(usdc),
RouteTypesV2.Provider.Curve,
address(curvePool),
abi.encode(int128(0), int128(1), false),
true
);
router.setProviderRoute(
address(weth),
address(usdt),
RouteTypesV2.Provider.OneInch,
address(oneInchRouter),
abi.encode(address(oneInchRouter), address(oneInchRouter), bytes("")),
true
);
weth.mint(user, 10 ether);
usdt.mint(user, 50_000 * 1e6);
}
function testUniswapPilotQuotesAndExecutes() public {
uint256 quote = uniswapRouter.quoteExactInputSingle(address(weth), address(usdt), 3000, 1 ether, 0);
assertGt(quote, 0);
vm.startPrank(user);
weth.approve(address(router), 1 ether);
RouteTypesV2.RouteLeg[] memory legs = new RouteTypesV2.RouteLeg[](1);
legs[0] = RouteTypesV2.RouteLeg({
provider: RouteTypesV2.Provider.UniswapV3,
tokenIn: address(weth),
tokenOut: address(usdt),
amountSource: RouteTypesV2.AmountSource.UserInput,
minAmountOut: quote - 1,
target: address(uniswapRouter),
providerData: abi.encode(bytes(""), uint24(3000), address(uniswapRouter), false)
});
RouteTypesV2.RoutePlan memory plan = RouteTypesV2.RoutePlan({
chainId: block.chainid,
inputToken: address(weth),
outputToken: address(usdt),
amountIn: 1 ether,
minAmountOut: quote - 1,
recipient: user,
deadline: block.timestamp + 300,
legs: legs
});
uint256 amountOut = router.executeRoute(plan);
vm.stopPrank();
assertEq(amountOut, quote);
}
function testBalancerPilotExecutes() public {
vm.startPrank(user);
weth.approve(address(router), 1 ether);
RouteTypesV2.RouteLeg[] memory legs = new RouteTypesV2.RouteLeg[](1);
legs[0] = RouteTypesV2.RouteLeg({
provider: RouteTypesV2.Provider.Balancer,
tokenIn: address(weth),
tokenOut: address(usdc),
amountSource: RouteTypesV2.AmountSource.UserInput,
minAmountOut: 1_000 * 1e6,
target: address(balancerVault),
providerData: abi.encode(BALANCER_POOL_ID)
});
RouteTypesV2.RoutePlan memory plan = RouteTypesV2.RoutePlan({
chainId: block.chainid,
inputToken: address(weth),
outputToken: address(usdc),
amountIn: 1 ether,
minAmountOut: 1_000 * 1e6,
recipient: user,
deadline: block.timestamp + 300,
legs: legs
});
uint256 amountOut = router.executeRoute(plan);
vm.stopPrank();
assertGt(amountOut, 0);
}
function testCurvePilotExecutes() public {
vm.startPrank(user);
usdt.approve(address(router), 10_000 * 1e6);
RouteTypesV2.RouteLeg[] memory legs = new RouteTypesV2.RouteLeg[](1);
legs[0] = RouteTypesV2.RouteLeg({
provider: RouteTypesV2.Provider.Curve,
tokenIn: address(usdt),
tokenOut: address(usdc),
amountSource: RouteTypesV2.AmountSource.UserInput,
minAmountOut: 9_900 * 1e6,
target: address(curvePool),
providerData: abi.encode(int128(0), int128(1), false)
});
RouteTypesV2.RoutePlan memory plan = RouteTypesV2.RoutePlan({
chainId: block.chainid,
inputToken: address(usdt),
outputToken: address(usdc),
amountIn: 10_000 * 1e6,
minAmountOut: 9_900 * 1e6,
recipient: user,
deadline: block.timestamp + 300,
legs: legs
});
uint256 amountOut = router.executeRoute(plan);
vm.stopPrank();
assertGt(amountOut, 0);
}
function testOneInchPilotExecutes() public {
vm.startPrank(user);
weth.approve(address(router), 1 ether);
RouteTypesV2.RouteLeg[] memory legs = new RouteTypesV2.RouteLeg[](1);
legs[0] = RouteTypesV2.RouteLeg({
provider: RouteTypesV2.Provider.OneInch,
tokenIn: address(weth),
tokenOut: address(usdt),
amountSource: RouteTypesV2.AmountSource.UserInput,
minAmountOut: 1_000 * 1e6,
target: address(oneInchRouter),
providerData: abi.encode(address(oneInchRouter), address(oneInchRouter), bytes(""))
});
RouteTypesV2.RoutePlan memory plan = RouteTypesV2.RoutePlan({
chainId: block.chainid,
inputToken: address(weth),
outputToken: address(usdt),
amountIn: 1 ether,
minAmountOut: 1_000 * 1e6,
recipient: user,
deadline: block.timestamp + 300,
legs: legs
});
uint256 amountOut = router.executeRoute(plan);
vm.stopPrank();
assertGt(amountOut, 0);
}
}