chore: Improve tests:
In both encoding and contracts: - Make sure that the tests names/encoder match what is happening (we had test_split_... that was only a single swap). - Made modules inside the encodings tests - In swap_encoders: there is one module per protocol - In strategy_encoders: there is one module per strategy and an extra protocol_integration module. Inside the sequential module there is another module called chained_swaps - In contracts, each strategy has its own file. Integration tests per strategy should also be here. Renamed TychoRouterIntegration to TychoRouterProtocolIntegration. Only protocol integration tests should be in this file --- don't change below this line --- ENG-4327 Took 1 hour 13 minutes
This commit is contained in:
@@ -1,315 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BUSL-1.1
|
|
||||||
pragma solidity ^0.8.26;
|
|
||||||
|
|
||||||
import "./TychoRouterTestSetup.sol";
|
|
||||||
|
|
||||||
contract TychoRouterTestIntegration is TychoRouterTestSetup {
|
|
||||||
function testSplitSwapSingleWithoutPermit2Integration() public {
|
|
||||||
// Tests swapping WETH -> DAI on a USV2 pool without permit2
|
|
||||||
deal(WETH_ADDR, ALICE, 1 ether);
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(DAI_ADDR).balanceOf(ALICE);
|
|
||||||
// Encoded solution generated using `test_split_swap_strategy_encoder_no_permit2`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae37400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000100000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE);
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 2659881924818443699787);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitUSV4Integration() public {
|
|
||||||
// Test created with calldata from our router encoder.
|
|
||||||
|
|
||||||
// Performs a sequential swap from USDC to PEPE though ETH using two
|
|
||||||
// consecutive USV4 pools
|
|
||||||
//
|
|
||||||
// USDC ──(USV4)──> ETH ───(USV4)──> PEPE
|
|
||||||
//
|
|
||||||
deal(USDC_ADDR, ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_encoding_strategy_usv4`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041c96ca498573c3c283e270700101c963405003b631ce90988c3690248b5cab66a70a1cb074afa6acf671300c917b8d6ac0149ae538c95a67a844175bfa9ae7d811b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d008b0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d23119330004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 97191013220606467325121599);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitUSV4IntegrationInputETH() public {
|
|
||||||
// Test created with calldata from our router encoder.
|
|
||||||
|
|
||||||
// Performs a single swap from ETH to PEPE without wrapping or unwrapping
|
|
||||||
//
|
|
||||||
// ETH ───(USV4)──> PEPE
|
|
||||||
//
|
|
||||||
deal(ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Encoded solution generated using `test_split_encoding_strategy_usv4_eth_in`
|
|
||||||
(bool success,) = tychoRouterAddr.call{value: 1 ether}(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004197c8f24177a14b631dd3a9226c08a0a376fcaf7894364b5131db4415890fc2c57a48bb5497d36a57a4aa359fd6781788c697f6a85500d7bee3e7a1597f0900b81b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 242373460199848577067005852);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitUSV4IntegrationOutputETH() public {
|
|
||||||
// Test created with calldata from our router encoder.
|
|
||||||
|
|
||||||
// Performs a single swap from USDC to ETH without wrapping or unwrapping
|
|
||||||
//
|
|
||||||
// USDC ───(USV4)──> ETH
|
|
||||||
//
|
|
||||||
deal(USDC_ADDR, ALICE, 3000_000000);
|
|
||||||
uint256 balanceBefore = ALICE.balance;
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
|
|
||||||
// Encoded solution generated using `test_split_encoding_strategy_usv4_eth_out`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041dbb84c68a4293bcf6303ca45327614667c54226086ddcfa2daa9289c1657da9a57268f4d8ceea3c831d43e5a96b1dc54766bc3fda8845d5c7e266981b9d84c651b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c00000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = ALICE.balance;
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
console.logUint(balanceAfter - balanceBefore);
|
|
||||||
assertEq(balanceAfter - balanceBefore, 1117254495486192350);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitSwapSingleWithWrapIntegration() public {
|
|
||||||
// Tests swapping WETH -> DAI on a USV2 pool, but ETH is received from the user
|
|
||||||
// and wrapped before the swap
|
|
||||||
deal(ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(DAI_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
// Encoded solution generated using `test_split_swap_strategy_encoder_wrap`
|
|
||||||
(bool success,) = tychoRouterAddr.call{value: 1 ether}(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000068261ff900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9a01000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041eaba97110bc7c3586bf8fa3d3d2c24a3863e84d2e1688689e325e750f860802d745309e3dc818fe029f439c14a52d9a3f48f2873733259c342eb01bdf8ac896b1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700020000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 2659881924818443699787);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitSwapSingleWithUnwrapIntegration() public {
|
|
||||||
// Tests swapping DAI -> WETH on a USV2 pool, and WETH is unwrapped to ETH
|
|
||||||
// before sending back to the user
|
|
||||||
deal(DAI_ADDR, ALICE, 3000 ether);
|
|
||||||
uint256 balanceBefore = ALICE.balance;
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_swap_strategy_encoder_unwrap`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe93420000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c401d4a22c3e0b693b4f9d0807f6107ab6b6d6b716a45978ba175af6e717ae617d4c13b8603db25ee6902b807ee049588ce27030bf3f60833bf26e9561f560c1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395010200000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = ALICE.balance;
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 1120007305574805922);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitEkuboIntegration() public {
|
|
||||||
// Test needs to be run on block 22082754 or later
|
|
||||||
// notice that the addresses for the tycho router and the executors are different because we are redeploying
|
|
||||||
vm.rollFork(22082754);
|
|
||||||
tychoRouter = deployRouter();
|
|
||||||
address[] memory executors = deployExecutors();
|
|
||||||
vm.startPrank(EXECUTOR_SETTER);
|
|
||||||
tychoRouter.setExecutors(executors);
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
deal(ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
// Encoded solution generated using `test_split_encoding_strategy_ekubo`
|
|
||||||
(bool success,) = address(tychoRouter).call{value: 1 ether}(
|
|
||||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000078007600010000003d7ebc40af7092e3f1c81f2e996cba5cae2090d705cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c0000000000000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertGe(balanceAfter - balanceBefore, 26173932);
|
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitSwapIntegration() public {
|
|
||||||
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
|
||||||
//
|
|
||||||
// ┌──(USV2)──> WBTC ───(USV2)──> USDC
|
|
||||||
// WETH ─┤
|
|
||||||
// └──(USV2)──> DAI ───(USV2)──> USDC
|
|
||||||
deal(WETH_ADDR, ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_swap_strategy_encoder_complex_route`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010000000000000000000000000000000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertGe(balanceAfter - balanceBefore, 26173932);
|
|
||||||
|
|
||||||
// All input tokens are transferred to the router at first. Make sure we used
|
|
||||||
// all of it (and thus our splits are correct).
|
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSequentialSwapIntegrationPermit2() public {
|
|
||||||
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
|
||||||
//
|
|
||||||
// WETH ──(USV2)──> WBTC ───(USV2)──> USDC
|
|
||||||
deal(WETH_ADDR, ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_sequential_swap_strategy_encoder_complex_route`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682714ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067ff8eb300000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412fe66c22814eb271e37bb03303bae445eb96aa50fae9680a0ae685ee5795aebf1f5bb7718154c69680bcfc00cc9be525b2b021f57a1bddb4db622139acd425d41b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 2552915143);
|
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSequentialSwapIntegration() public {
|
|
||||||
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
|
||||||
//
|
|
||||||
// WETH ──(USV2)──> WBTC ───(USV2)──> USDC
|
|
||||||
deal(WETH_ADDR, ALICE, 1 ether);
|
|
||||||
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_sequential_swap_strategy_encoder_no_permit2`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(balanceAfter - balanceBefore, 2552915143);
|
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testCyclicSequentialSwapIntegration() public {
|
|
||||||
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_cyclic_sequential_swap_split_strategy`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682714ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067ff8eb30000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000417badef4d6a9158869bdd061a492f6ca4eb4e012b9295f5562414f83ccbc37982241b4de1d934b4f9f0d51f792b12019f806953e7a7ba49d6cfe0487458753e871b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d80000"
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99889294);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitInputCyclicSwapIntegration() public {
|
|
||||||
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_input_cyclic_swap`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99574171);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitOutputCyclicSwapIntegration() public {
|
|
||||||
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
|
||||||
|
|
||||||
// Approve permit2
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_output_cyclic_swap`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99525908);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSplitCurveIntegration() public {
|
|
||||||
deal(UWU_ADDR, ALICE, 1 ether);
|
|
||||||
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
IERC20(UWU_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
|
||||||
// Encoded solution generated using `test_split_encoding_strategy_curve`
|
|
||||||
(bool success,) = tychoRouterAddr.call(
|
|
||||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000070006e00010000001d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e710201000103cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(success, "Call Failed");
|
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 4691958787921);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
127
foundry/test/TychoRouterProtocolIntegration.t.sol
Normal file
127
foundry/test/TychoRouterProtocolIntegration.t.sol
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
import "./TychoRouterTestSetup.sol";
|
||||||
|
|
||||||
|
contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup {
|
||||||
|
function testSequentialUSV4Integration() public {
|
||||||
|
// Test created with calldata from our router encoder.
|
||||||
|
|
||||||
|
// Performs a sequential swap from USDC to PEPE though ETH using two
|
||||||
|
// consecutive USV4 pools
|
||||||
|
//
|
||||||
|
// USDC ──(USV4)──> ETH ───(USV4)──> PEPE
|
||||||
|
//
|
||||||
|
deal(USDC_ADDR, ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_sequential_encoding_strategy_usv4`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"51bcc7b6000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000682db60700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006806300f00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041c5715acd97f16c669ba5b6a15d911e61f9b5a056c1bb4f0576dbf7c1251bddd70ac5e929270186517e593e1c8d1d1ecf5c742576affcd5d64cac409600ad054e1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000880086f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d23119330004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f4000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 97191013220606467325121599);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSingleUSV4IntegrationInputETH() public {
|
||||||
|
// Test created with calldata from our router encoder.
|
||||||
|
|
||||||
|
// Performs a single swap from ETH to PEPE without wrapping or unwrapping
|
||||||
|
//
|
||||||
|
// ETH ───(USV4)──> PEPE
|
||||||
|
//
|
||||||
|
deal(ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Encoded solution generated using `test_single_encoding_strategy_usv4_eth_in`
|
||||||
|
(bool success,) = tychoRouterAddr.call{value: 1 ether}(
|
||||||
|
hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682db9c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680633c800000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000417d375e095d10a0d69c183082f533f2393e7ec356e4d222d32943ecab59683b013047017436b824fb8d00c2cdda2ab4136da5bc32ea79c6305b237633f6d0978c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cf62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 242373460199848577067005852);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSingleUSV4IntegrationOutputETH() public {
|
||||||
|
// Test created with calldata from our router encoder.
|
||||||
|
|
||||||
|
// Performs a single swap from USDC to ETH without wrapping or unwrapping
|
||||||
|
//
|
||||||
|
// USDC ───(USV4)──> ETH
|
||||||
|
//
|
||||||
|
deal(USDC_ADDR, ALICE, 3000_000000);
|
||||||
|
uint256 balanceBefore = ALICE.balance;
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
|
||||||
|
// Encoded solution generated using `test_single_encoding_strategy_usv4_eth_out`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041dbb84c68a4293bcf6303ca45327614667c54226086ddcfa2daa9289c1657da9a57268f4d8ceea3c831d43e5a96b1dc54766bc3fda8845d5c7e266981b9d84c651b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c00000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = ALICE.balance;
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
console.logUint(balanceAfter - balanceBefore);
|
||||||
|
assertEq(balanceAfter - balanceBefore, 1117254495486192350);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSingleEkuboIntegration() public {
|
||||||
|
// Test needs to be run on block 22082754 or later
|
||||||
|
// notice that the addresses for the tycho router and the executors are different because we are redeploying
|
||||||
|
vm.rollFork(22082754);
|
||||||
|
tychoRouter = deployRouter();
|
||||||
|
address[] memory executors = deployExecutors();
|
||||||
|
vm.startPrank(EXECUTOR_SETTER);
|
||||||
|
tychoRouter.setExecutors(executors);
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
deal(ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
// Encoded solution generated using `test_single_encoding_strategy_ekubo`
|
||||||
|
(bool success,) = address(tychoRouter).call{value: 1 ether}(
|
||||||
|
hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000713d7ebc40af7092e3f1c81f2e996cba5cae2090d705cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertGe(balanceAfter - balanceBefore, 26173932);
|
||||||
|
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSingleCurveIntegration() public {
|
||||||
|
deal(UWU_ADDR, ALICE, 1 ether);
|
||||||
|
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(UWU_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_single_encoding_strategy_curve`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000691d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e710201000103cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 4691958787921);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -341,6 +341,71 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99889294);
|
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99889294);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSequentialSwapIntegrationPermit2() public {
|
||||||
|
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
||||||
|
//
|
||||||
|
// WETH ──(USV2)──> WBTC ───(USV2)──> USDC
|
||||||
|
deal(WETH_ADDR, ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_sequential_swap_strategy_encoder`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682714ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067ff8eb300000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412fe66c22814eb271e37bb03303bae445eb96aa50fae9680a0ae685ee5795aebf1f5bb7718154c69680bcfc00cc9be525b2b021f57a1bddb4db622139acd425d41b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 2552915143);
|
||||||
|
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSequentialSwapIntegration() public {
|
||||||
|
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
||||||
|
//
|
||||||
|
// WETH ──(USV2)──> WBTC ───(USV2)──> USDC
|
||||||
|
deal(WETH_ADDR, ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_sequential_swap_strategy_encoder_no_permit2`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 2552915143);
|
||||||
|
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSequentialCyclicSwapIntegration() public {
|
||||||
|
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_sequential_strategy_cyclic_swap`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"51bcc7b60000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682dbba300000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680635ab00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041adc1487dd76b622c3762cfeb017fc51d2e3513e8e2e2a6a8d8e153d79192474735457ed064158c007ffc2a42cc8ee7ccc256155dbe4ef3b5404c4addbeb5612a1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640010200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99889294);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
function testUSV3USV2Integration() public {
|
function testUSV3USV2Integration() public {
|
||||||
// Performs a sequential swap from WETH to USDC though WBTC and DAI using USV3 and USV2 pools
|
// Performs a sequential swap from WETH to USDC though WBTC and DAI using USV3 and USV2 pools
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -324,4 +324,47 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
assertTrue(success, "Call Failed");
|
assertTrue(success, "Call Failed");
|
||||||
assertEq(balanceAfter - balanceBefore, 2659881924818443699787);
|
assertEq(balanceAfter - balanceBefore, 2659881924818443699787);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSingleSwapWithWrapIntegration() public {
|
||||||
|
// Tests swapping WETH -> DAI on a USV2 pool, but ETH is received from the user
|
||||||
|
// and wrapped before the swap
|
||||||
|
deal(ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(DAI_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
// Encoded solution generated using `test_single_swap_strategy_encoder_wrap`
|
||||||
|
(bool success,) = tychoRouterAddr.call{value: 1 ether}(
|
||||||
|
hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682db3ee00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068062df600000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412bda9e4c6208c6851db4a383761f0511ace6a071dafcb8c017f312777d11988f50d017cc914ea2db8a8082a469584bff851efc00533b803fcc1aa4ada81c6c9e1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 2659881924818443699787);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSingleSwapWithUnwrapIntegration() public {
|
||||||
|
// Tests swapping DAI -> WETH on a USV2 pool, and WETH is unwrapped to ETH
|
||||||
|
// before sending back to the user
|
||||||
|
deal(DAI_ADDR, ALICE, 3000 ether);
|
||||||
|
uint256 balanceBefore = ALICE.balance;
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_single_swap_strategy_encoder_unwrap`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"30ace1b10000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be0000000000000000000000000000000000000000000000000000000000000682db45d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068062e6500000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041de45f1a73e8a22fc958af300f93cff06b49e74667bb29b810aed4254fef0dae6340ceb95265d81f5b158bcade2b5a2e3efa8bfa521a6466c0b1ce0bcfddc19d21c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501020000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = ALICE.balance;
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(balanceAfter - balanceBefore, 1120007305574805922);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -657,4 +657,67 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps));
|
tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps));
|
||||||
assertGt(IERC20(BASE_MAG7).balanceOf(tychoRouterAddr), 1379830606);
|
assertGt(IERC20(BASE_MAG7).balanceOf(tychoRouterAddr), 1379830606);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSplitSwapIntegration() public {
|
||||||
|
// Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools
|
||||||
|
//
|
||||||
|
// ┌──(USV2)──> WBTC ───(USV2)──> USDC
|
||||||
|
// WETH ─┤
|
||||||
|
// └──(USV2)──> DAI ───(USV2)──> USDC
|
||||||
|
deal(WETH_ADDR, ALICE, 1 ether);
|
||||||
|
uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_split_swap_strategy_encoder`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010000000000000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertGe(balanceAfter - balanceBefore, 26173932);
|
||||||
|
|
||||||
|
// All input tokens are transferred to the router at first. Make sure we used
|
||||||
|
// all of it (and thus our splits are correct).
|
||||||
|
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSplitInputCyclicSwapIntegration() public {
|
||||||
|
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_split_input_cyclic_swap`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99574171);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSplitOutputCyclicSwapIntegration() public {
|
||||||
|
deal(USDC_ADDR, ALICE, 100 * 10 ** 6);
|
||||||
|
|
||||||
|
// Approve permit2
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
|
// Encoded solution generated using `test_split_output_cyclic_swap`
|
||||||
|
(bool success,) = tychoRouterAddr.call(
|
||||||
|
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(success, "Call Failed");
|
||||||
|
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99525908);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -577,419 +577,435 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::encoding::models::TransferType;
|
use crate::encoding::models::TransferType;
|
||||||
|
|
||||||
#[test]
|
mod uniswap_v2 {
|
||||||
fn test_encode_uniswap_v2() {
|
use super::*;
|
||||||
let usv2_pool = ProtocolComponent {
|
#[test]
|
||||||
id: String::from("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
fn test_encode_uniswap_v2() {
|
||||||
..Default::default()
|
let usv2_pool = ProtocolComponent {
|
||||||
};
|
id: String::from("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
||||||
let token_out = Bytes::from("0x6b175474e89094c44da98b954eedeac495271d0f");
|
let token_out = Bytes::from("0x6b175474e89094c44da98b954eedeac495271d0f");
|
||||||
let swap = Swap {
|
let swap = Swap {
|
||||||
component: usv2_pool,
|
component: usv2_pool,
|
||||||
token_in: token_in.clone(),
|
token_in: token_in.clone(),
|
||||||
token_out: token_out.clone(),
|
token_out: token_out.clone(),
|
||||||
split: 0f64,
|
split: 0f64,
|
||||||
};
|
};
|
||||||
let encoding_context = EncodingContext {
|
let encoding_context = EncodingContext {
|
||||||
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
||||||
exact_out: false,
|
exact_out: false,
|
||||||
router_address: Some(Bytes::zero(20)),
|
router_address: Some(Bytes::zero(20)),
|
||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::TransferToProtocol,
|
transfer_type: TransferType::TransferToProtocol,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV2SwapEncoder::new(
|
let encoder = UniswapV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
TychoCoreChain::Ethereum.into(),
|
TychoCoreChain::Ethereum.into(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
|
||||||
let encoded_swap = encoder
|
|
||||||
.encode_swap(swap, encoding_context)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hex_swap = encode(&encoded_swap);
|
let encoded_swap = encoder
|
||||||
assert_eq!(
|
.encode_swap(swap, encoding_context)
|
||||||
hex_swap,
|
.unwrap();
|
||||||
String::from(concat!(
|
let hex_swap = encode(&encoded_swap);
|
||||||
// in token
|
assert_eq!(
|
||||||
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
hex_swap,
|
||||||
// component id
|
String::from(concat!(
|
||||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
|
// in token
|
||||||
// receiver
|
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||||
"0000000000000000000000000000000000000001",
|
// component id
|
||||||
// zero for one
|
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
|
||||||
"00",
|
// receiver
|
||||||
// transfer type (transfer)
|
"0000000000000000000000000000000000000001",
|
||||||
"00",
|
// zero for one
|
||||||
))
|
"00",
|
||||||
);
|
// transfer type (transfer)
|
||||||
}
|
"00",
|
||||||
#[test]
|
))
|
||||||
fn test_encode_uniswap_v3() {
|
);
|
||||||
let fee = BigInt::from(500);
|
}
|
||||||
let encoded_pool_fee = Bytes::from(fee.to_signed_bytes_be());
|
|
||||||
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
|
||||||
static_attributes.insert("fee".into(), Bytes::from(encoded_pool_fee.to_vec()));
|
|
||||||
|
|
||||||
let usv3_pool = ProtocolComponent {
|
|
||||||
id: String::from("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
|
||||||
static_attributes,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
|
||||||
let token_out = Bytes::from("0x6b175474e89094c44da98b954eedeac495271d0f");
|
|
||||||
let swap = Swap {
|
|
||||||
component: usv3_pool,
|
|
||||||
token_in: token_in.clone(),
|
|
||||||
token_out: token_out.clone(),
|
|
||||||
split: 0f64,
|
|
||||||
};
|
|
||||||
let encoding_context = EncodingContext {
|
|
||||||
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
|
||||||
exact_out: false,
|
|
||||||
router_address: Some(Bytes::zero(20)),
|
|
||||||
group_token_in: token_in.clone(),
|
|
||||||
group_token_out: token_out.clone(),
|
|
||||||
transfer_type: TransferType::TransferToProtocol,
|
|
||||||
};
|
|
||||||
let encoder = UniswapV3SwapEncoder::new(
|
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
|
||||||
TychoCoreChain::Ethereum.into(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let encoded_swap = encoder
|
|
||||||
.encode_swap(swap, encoding_context)
|
|
||||||
.unwrap();
|
|
||||||
let hex_swap = encode(&encoded_swap);
|
|
||||||
assert_eq!(
|
|
||||||
hex_swap,
|
|
||||||
String::from(concat!(
|
|
||||||
// in token
|
|
||||||
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
||||||
// out token
|
|
||||||
"6b175474e89094c44da98b954eedeac495271d0f",
|
|
||||||
// fee
|
|
||||||
"0001f4",
|
|
||||||
// receiver
|
|
||||||
"0000000000000000000000000000000000000001",
|
|
||||||
// pool id
|
|
||||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
|
|
||||||
// zero for one
|
|
||||||
"00",
|
|
||||||
// transfer type (transfer)
|
|
||||||
"00",
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
mod uniswap_v3 {
|
||||||
fn test_encode_balancer_v2() {
|
use super::*;
|
||||||
let balancer_pool = ProtocolComponent {
|
#[test]
|
||||||
id: String::from("0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014"),
|
fn test_encode_uniswap_v3() {
|
||||||
protocol_system: String::from("vm:balancer_v2"),
|
let fee = BigInt::from(500);
|
||||||
..Default::default()
|
let encoded_pool_fee = Bytes::from(fee.to_signed_bytes_be());
|
||||||
};
|
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
||||||
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
static_attributes.insert("fee".into(), Bytes::from(encoded_pool_fee.to_vec()));
|
||||||
let token_out = Bytes::from("0xba100000625a3754423978a60c9317c58a424e3D");
|
|
||||||
let swap = Swap {
|
|
||||||
component: balancer_pool,
|
|
||||||
token_in: token_in.clone(),
|
|
||||||
token_out: token_out.clone(),
|
|
||||||
split: 0f64,
|
|
||||||
};
|
|
||||||
let encoding_context = EncodingContext {
|
|
||||||
// The receiver was generated with `makeAddr("bob") using forge`
|
|
||||||
receiver: Bytes::from("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"),
|
|
||||||
exact_out: false,
|
|
||||||
router_address: Some(Bytes::zero(20)),
|
|
||||||
group_token_in: token_in.clone(),
|
|
||||||
group_token_out: token_out.clone(),
|
|
||||||
transfer_type: TransferType::None,
|
|
||||||
};
|
|
||||||
let encoder = BalancerV2SwapEncoder::new(
|
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
|
||||||
TychoCoreChain::Ethereum.into(),
|
|
||||||
Some(HashMap::from([(
|
|
||||||
"vault_address".to_string(),
|
|
||||||
"0xba12222222228d8ba445958a75a0704d566bf2c8".to_string(),
|
|
||||||
)])),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let encoded_swap = encoder
|
|
||||||
.encode_swap(swap, encoding_context)
|
|
||||||
.unwrap();
|
|
||||||
let hex_swap = encode(&encoded_swap);
|
|
||||||
|
|
||||||
assert_eq!(
|
let usv3_pool = ProtocolComponent {
|
||||||
hex_swap,
|
id: String::from("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||||
String::from(concat!(
|
static_attributes,
|
||||||
// token in
|
..Default::default()
|
||||||
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
};
|
||||||
// token out
|
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
||||||
"ba100000625a3754423978a60c9317c58a424e3d",
|
let token_out = Bytes::from("0x6b175474e89094c44da98b954eedeac495271d0f");
|
||||||
// pool id
|
let swap = Swap {
|
||||||
"5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014",
|
component: usv3_pool,
|
||||||
// receiver
|
token_in: token_in.clone(),
|
||||||
"1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
|
token_out: token_out.clone(),
|
||||||
// approval needed
|
split: 0f64,
|
||||||
"01",
|
};
|
||||||
// transfer type
|
let encoding_context = EncodingContext {
|
||||||
"05"
|
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
||||||
))
|
exact_out: false,
|
||||||
);
|
router_address: Some(Bytes::zero(20)),
|
||||||
|
group_token_in: token_in.clone(),
|
||||||
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::TransferToProtocol,
|
||||||
|
};
|
||||||
|
let encoder = UniswapV3SwapEncoder::new(
|
||||||
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
|
TychoCoreChain::Ethereum.into(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let encoded_swap = encoder
|
||||||
|
.encode_swap(swap, encoding_context)
|
||||||
|
.unwrap();
|
||||||
|
let hex_swap = encode(&encoded_swap);
|
||||||
|
assert_eq!(
|
||||||
|
hex_swap,
|
||||||
|
String::from(concat!(
|
||||||
|
// in token
|
||||||
|
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||||
|
// out token
|
||||||
|
"6b175474e89094c44da98b954eedeac495271d0f",
|
||||||
|
// fee
|
||||||
|
"0001f4",
|
||||||
|
// receiver
|
||||||
|
"0000000000000000000000000000000000000001",
|
||||||
|
// pool id
|
||||||
|
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
|
||||||
|
// zero for one
|
||||||
|
"00",
|
||||||
|
// transfer type (transfer)
|
||||||
|
"00",
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
mod balancer_v2 {
|
||||||
fn test_encode_uniswap_v4_simple_swap() {
|
use super::*;
|
||||||
let fee = BigInt::from(100);
|
|
||||||
let tick_spacing = BigInt::from(1);
|
|
||||||
let token_in = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"); // USDE
|
|
||||||
let token_out = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"); // USDT
|
|
||||||
|
|
||||||
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
#[test]
|
||||||
static_attributes.insert("key_lp_fee".into(), Bytes::from(fee.to_signed_bytes_be()));
|
fn test_encode_balancer_v2() {
|
||||||
static_attributes
|
let balancer_pool = ProtocolComponent {
|
||||||
.insert("tick_spacing".into(), Bytes::from(tick_spacing.to_signed_bytes_be()));
|
id: String::from(
|
||||||
|
"0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014",
|
||||||
let usv4_pool = ProtocolComponent {
|
),
|
||||||
// Pool manager
|
protocol_system: String::from("vm:balancer_v2"),
|
||||||
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
..Default::default()
|
||||||
static_attributes,
|
};
|
||||||
..Default::default()
|
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
||||||
};
|
let token_out = Bytes::from("0xba100000625a3754423978a60c9317c58a424e3D");
|
||||||
let swap = Swap {
|
let swap = Swap {
|
||||||
component: usv4_pool,
|
component: balancer_pool,
|
||||||
token_in: token_in.clone(),
|
token_in: token_in.clone(),
|
||||||
token_out: token_out.clone(),
|
token_out: token_out.clone(),
|
||||||
split: 0f64,
|
split: 0f64,
|
||||||
};
|
};
|
||||||
let encoding_context = EncodingContext {
|
let encoding_context = EncodingContext {
|
||||||
// The receiver is ALICE to match the solidity tests
|
// The receiver was generated with `makeAddr("bob") using forge`
|
||||||
receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"),
|
receiver: Bytes::from("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"),
|
||||||
exact_out: false,
|
exact_out: false,
|
||||||
// Same as the executor address
|
router_address: Some(Bytes::zero(20)),
|
||||||
router_address: Some(Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f")),
|
group_token_in: token_in.clone(),
|
||||||
|
group_token_out: token_out.clone(),
|
||||||
group_token_in: token_in.clone(),
|
transfer_type: TransferType::None,
|
||||||
group_token_out: token_out.clone(),
|
};
|
||||||
transfer_type: TransferType::TransferToProtocol,
|
let encoder = BalancerV2SwapEncoder::new(
|
||||||
};
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
TychoCoreChain::Ethereum.into(),
|
||||||
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
Some(HashMap::from([(
|
||||||
TychoCoreChain::Ethereum.into(),
|
"vault_address".to_string(),
|
||||||
None,
|
"0xba12222222228d8ba445958a75a0704d566bf2c8".to_string(),
|
||||||
)
|
)])),
|
||||||
.unwrap();
|
)
|
||||||
let encoded_swap = encoder
|
|
||||||
.encode_swap(swap, encoding_context)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hex_swap = encode(&encoded_swap);
|
let encoded_swap = encoder
|
||||||
println!("test_encode_uniswap_v4_simple_swap: {}", hex_swap);
|
.encode_swap(swap, encoding_context)
|
||||||
|
.unwrap();
|
||||||
|
let hex_swap = encode(&encoded_swap);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex_swap,
|
hex_swap,
|
||||||
String::from(concat!(
|
String::from(concat!(
|
||||||
// group token in
|
// token in
|
||||||
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||||
// group token out
|
// token out
|
||||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
"ba100000625a3754423978a60c9317c58a424e3d",
|
||||||
// zero for one
|
// pool id
|
||||||
"01",
|
"5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014",
|
||||||
// transfer type
|
// receiver
|
||||||
"00",
|
"1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
|
||||||
// receiver
|
// approval needed
|
||||||
"cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2",
|
"01",
|
||||||
// pool params:
|
// transfer type
|
||||||
// - intermediary token
|
"05"
|
||||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
))
|
||||||
// - fee
|
);
|
||||||
"000064",
|
}
|
||||||
// - tick spacing
|
|
||||||
"000001"
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
mod uniswap_v4 {
|
||||||
fn test_encode_uniswap_v4_second_swap() {
|
use super::*;
|
||||||
let fee = BigInt::from(3000);
|
|
||||||
let tick_spacing = BigInt::from(60);
|
|
||||||
let group_token_in = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"); // USDE
|
|
||||||
let token_in = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"); // USDT
|
|
||||||
let token_out = Bytes::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"); // WBTC
|
|
||||||
|
|
||||||
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
#[test]
|
||||||
static_attributes.insert("key_lp_fee".into(), Bytes::from(fee.to_signed_bytes_be()));
|
fn test_encode_uniswap_v4_simple_swap() {
|
||||||
static_attributes
|
let fee = BigInt::from(100);
|
||||||
.insert("tick_spacing".into(), Bytes::from(tick_spacing.to_signed_bytes_be()));
|
let tick_spacing = BigInt::from(1);
|
||||||
|
let token_in = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"); // USDE
|
||||||
|
let token_out = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"); // USDT
|
||||||
|
|
||||||
let usv4_pool = ProtocolComponent {
|
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
||||||
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
static_attributes.insert("key_lp_fee".into(), Bytes::from(fee.to_signed_bytes_be()));
|
||||||
static_attributes,
|
static_attributes
|
||||||
..Default::default()
|
.insert("tick_spacing".into(), Bytes::from(tick_spacing.to_signed_bytes_be()));
|
||||||
};
|
|
||||||
|
|
||||||
let swap = Swap {
|
let usv4_pool = ProtocolComponent {
|
||||||
component: usv4_pool,
|
// Pool manager
|
||||||
token_in: token_in.clone(),
|
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
||||||
token_out: token_out.clone(),
|
static_attributes,
|
||||||
split: 0f64,
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
let swap = Swap {
|
||||||
|
component: usv4_pool,
|
||||||
|
token_in: token_in.clone(),
|
||||||
|
token_out: token_out.clone(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
let encoding_context = EncodingContext {
|
||||||
|
// The receiver is ALICE to match the solidity tests
|
||||||
|
receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"),
|
||||||
|
exact_out: false,
|
||||||
|
// Same as the executor address
|
||||||
|
router_address: Some(Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f")),
|
||||||
|
|
||||||
let encoding_context = EncodingContext {
|
group_token_in: token_in.clone(),
|
||||||
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
group_token_out: token_out.clone(),
|
||||||
exact_out: false,
|
transfer_type: TransferType::TransferToProtocol,
|
||||||
router_address: Some(Bytes::zero(20)),
|
};
|
||||||
group_token_in: group_token_in.clone(),
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
// Token out is the same as the group token out
|
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
||||||
group_token_out: token_out.clone(),
|
TychoCoreChain::Ethereum.into(),
|
||||||
transfer_type: TransferType::TransferToProtocol,
|
None,
|
||||||
};
|
)
|
||||||
|
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
|
||||||
TychoCoreChain::Ethereum.into(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let encoded_swap = encoder
|
|
||||||
.encode_swap(swap, encoding_context)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hex_swap = encode(&encoded_swap);
|
let encoded_swap = encoder
|
||||||
|
.encode_swap(swap, encoding_context)
|
||||||
|
.unwrap();
|
||||||
|
let hex_swap = encode(&encoded_swap);
|
||||||
|
println!("test_encode_uniswap_v4_simple_swap: {}", hex_swap);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex_swap,
|
hex_swap,
|
||||||
String::from(concat!(
|
String::from(concat!(
|
||||||
// pool params:
|
// group token in
|
||||||
// - intermediary token (20 bytes)
|
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
||||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
// group token out
|
||||||
// - fee (3 bytes)
|
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||||
"000bb8",
|
// zero for one
|
||||||
// - tick spacing (3 bytes)
|
"01",
|
||||||
"00003c"
|
// transfer type
|
||||||
))
|
"00",
|
||||||
);
|
// receiver
|
||||||
|
"cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2",
|
||||||
|
// pool params:
|
||||||
|
// - intermediary token
|
||||||
|
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||||
|
// - fee
|
||||||
|
"000064",
|
||||||
|
// - tick spacing
|
||||||
|
"000001"
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encode_uniswap_v4_second_swap() {
|
||||||
|
let fee = BigInt::from(3000);
|
||||||
|
let tick_spacing = BigInt::from(60);
|
||||||
|
let group_token_in = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"); // USDE
|
||||||
|
let token_in = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"); // USDT
|
||||||
|
let token_out = Bytes::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"); // WBTC
|
||||||
|
|
||||||
|
let mut static_attributes: HashMap<String, Bytes> = HashMap::new();
|
||||||
|
static_attributes.insert("key_lp_fee".into(), Bytes::from(fee.to_signed_bytes_be()));
|
||||||
|
static_attributes
|
||||||
|
.insert("tick_spacing".into(), Bytes::from(tick_spacing.to_signed_bytes_be()));
|
||||||
|
|
||||||
|
let usv4_pool = ProtocolComponent {
|
||||||
|
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
||||||
|
static_attributes,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let swap = Swap {
|
||||||
|
component: usv4_pool,
|
||||||
|
token_in: token_in.clone(),
|
||||||
|
token_out: token_out.clone(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
|
||||||
|
let encoding_context = EncodingContext {
|
||||||
|
receiver: Bytes::from("0x0000000000000000000000000000000000000001"),
|
||||||
|
exact_out: false,
|
||||||
|
router_address: Some(Bytes::zero(20)),
|
||||||
|
group_token_in: group_token_in.clone(),
|
||||||
|
// Token out is the same as the group token out
|
||||||
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::TransferToProtocol,
|
||||||
|
};
|
||||||
|
|
||||||
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
|
TychoCoreChain::Ethereum.into(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let encoded_swap = encoder
|
||||||
|
.encode_swap(swap, encoding_context)
|
||||||
|
.unwrap();
|
||||||
|
let hex_swap = encode(&encoded_swap);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
hex_swap,
|
||||||
|
String::from(concat!(
|
||||||
|
// pool params:
|
||||||
|
// - intermediary token (20 bytes)
|
||||||
|
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||||
|
// - fee (3 bytes)
|
||||||
|
"000bb8",
|
||||||
|
// - tick spacing (3 bytes)
|
||||||
|
"00003c"
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encode_uniswap_v4_sequential_swap() {
|
||||||
|
let usde_address = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3");
|
||||||
|
let usdt_address = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7");
|
||||||
|
let wbtc_address = Bytes::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599");
|
||||||
|
let router_address = Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f");
|
||||||
|
|
||||||
|
// The context is the same for both swaps, since the group token in and out are the same
|
||||||
|
let context = EncodingContext {
|
||||||
|
// The receiver is ALICE to match the solidity tests
|
||||||
|
receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"),
|
||||||
|
exact_out: false,
|
||||||
|
router_address: Some(router_address.clone()),
|
||||||
|
group_token_in: usde_address.clone(),
|
||||||
|
group_token_out: wbtc_address.clone(),
|
||||||
|
transfer_type: TransferType::TransferToProtocol,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup - First sequence: USDE -> USDT
|
||||||
|
let usde_usdt_fee = BigInt::from(100);
|
||||||
|
let usde_usdt_tick_spacing = BigInt::from(1);
|
||||||
|
|
||||||
|
let mut usde_usdt_static_attributes: HashMap<String, Bytes> = HashMap::new();
|
||||||
|
usde_usdt_static_attributes
|
||||||
|
.insert("key_lp_fee".into(), Bytes::from(usde_usdt_fee.to_signed_bytes_be()));
|
||||||
|
usde_usdt_static_attributes.insert(
|
||||||
|
"tick_spacing".into(),
|
||||||
|
Bytes::from(usde_usdt_tick_spacing.to_signed_bytes_be()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let usde_usdt_component = ProtocolComponent {
|
||||||
|
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
||||||
|
static_attributes: usde_usdt_static_attributes,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup - Second sequence: USDT -> WBTC
|
||||||
|
let usdt_wbtc_fee = BigInt::from(3000);
|
||||||
|
let usdt_wbtc_tick_spacing = BigInt::from(60);
|
||||||
|
|
||||||
|
let mut usdt_wbtc_static_attributes: HashMap<String, Bytes> = HashMap::new();
|
||||||
|
usdt_wbtc_static_attributes
|
||||||
|
.insert("key_lp_fee".into(), Bytes::from(usdt_wbtc_fee.to_signed_bytes_be()));
|
||||||
|
usdt_wbtc_static_attributes.insert(
|
||||||
|
"tick_spacing".into(),
|
||||||
|
Bytes::from(usdt_wbtc_tick_spacing.to_signed_bytes_be()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let usdt_wbtc_component = ProtocolComponent {
|
||||||
|
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
||||||
|
static_attributes: usdt_wbtc_static_attributes,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let initial_swap = Swap {
|
||||||
|
component: usde_usdt_component,
|
||||||
|
token_in: usde_address.clone(),
|
||||||
|
token_out: usdt_address.clone(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
|
||||||
|
let second_swap = Swap {
|
||||||
|
component: usdt_wbtc_component,
|
||||||
|
token_in: usdt_address,
|
||||||
|
token_out: wbtc_address.clone(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
|
||||||
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
|
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
||||||
|
TychoCoreChain::Ethereum.into(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let initial_encoded_swap = encoder
|
||||||
|
.encode_swap(initial_swap, context.clone())
|
||||||
|
.unwrap();
|
||||||
|
let second_encoded_swap = encoder
|
||||||
|
.encode_swap(second_swap, context)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let combined_hex =
|
||||||
|
format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap));
|
||||||
|
|
||||||
|
println!("test_encode_uniswap_v4_sequential_swap: {}", combined_hex);
|
||||||
|
assert_eq!(
|
||||||
|
combined_hex,
|
||||||
|
String::from(concat!(
|
||||||
|
// group_token in
|
||||||
|
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
||||||
|
// group_token out
|
||||||
|
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||||
|
// zero for one
|
||||||
|
"01",
|
||||||
|
// transfer type
|
||||||
|
"00",
|
||||||
|
// receiver
|
||||||
|
"cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2",
|
||||||
|
// pool params:
|
||||||
|
// - intermediary token USDT
|
||||||
|
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||||
|
// - fee
|
||||||
|
"000064",
|
||||||
|
// - tick spacing
|
||||||
|
"000001",
|
||||||
|
// - intermediary token WBTC
|
||||||
|
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||||
|
// - fee
|
||||||
|
"000bb8",
|
||||||
|
// - tick spacing
|
||||||
|
"00003c"
|
||||||
|
))
|
||||||
|
);
|
||||||
|
println!("{}", combined_hex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_encode_uniswap_v4_sequential_swap() {
|
|
||||||
let usde_address = Bytes::from("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3");
|
|
||||||
let usdt_address = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7");
|
|
||||||
let wbtc_address = Bytes::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599");
|
|
||||||
let router_address = Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f");
|
|
||||||
|
|
||||||
// The context is the same for both swaps, since the group token in and out are the same
|
|
||||||
let context = EncodingContext {
|
|
||||||
// The receiver is ALICE to match the solidity tests
|
|
||||||
receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"),
|
|
||||||
exact_out: false,
|
|
||||||
router_address: Some(router_address.clone()),
|
|
||||||
group_token_in: usde_address.clone(),
|
|
||||||
group_token_out: wbtc_address.clone(),
|
|
||||||
transfer_type: TransferType::TransferToProtocol,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup - First sequence: USDE -> USDT
|
|
||||||
let usde_usdt_fee = BigInt::from(100);
|
|
||||||
let usde_usdt_tick_spacing = BigInt::from(1);
|
|
||||||
|
|
||||||
let mut usde_usdt_static_attributes: HashMap<String, Bytes> = HashMap::new();
|
|
||||||
usde_usdt_static_attributes
|
|
||||||
.insert("key_lp_fee".into(), Bytes::from(usde_usdt_fee.to_signed_bytes_be()));
|
|
||||||
usde_usdt_static_attributes.insert(
|
|
||||||
"tick_spacing".into(),
|
|
||||||
Bytes::from(usde_usdt_tick_spacing.to_signed_bytes_be()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let usde_usdt_component = ProtocolComponent {
|
|
||||||
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
|
||||||
static_attributes: usde_usdt_static_attributes,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup - Second sequence: USDT -> WBTC
|
|
||||||
let usdt_wbtc_fee = BigInt::from(3000);
|
|
||||||
let usdt_wbtc_tick_spacing = BigInt::from(60);
|
|
||||||
|
|
||||||
let mut usdt_wbtc_static_attributes: HashMap<String, Bytes> = HashMap::new();
|
|
||||||
usdt_wbtc_static_attributes
|
|
||||||
.insert("key_lp_fee".into(), Bytes::from(usdt_wbtc_fee.to_signed_bytes_be()));
|
|
||||||
usdt_wbtc_static_attributes.insert(
|
|
||||||
"tick_spacing".into(),
|
|
||||||
Bytes::from(usdt_wbtc_tick_spacing.to_signed_bytes_be()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let usdt_wbtc_component = ProtocolComponent {
|
|
||||||
id: String::from("0x000000000004444c5dc75cB358380D2e3dE08A90"),
|
|
||||||
static_attributes: usdt_wbtc_static_attributes,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let initial_swap = Swap {
|
|
||||||
component: usde_usdt_component,
|
|
||||||
token_in: usde_address.clone(),
|
|
||||||
token_out: usdt_address.clone(),
|
|
||||||
split: 0f64,
|
|
||||||
};
|
|
||||||
|
|
||||||
let second_swap = Swap {
|
|
||||||
component: usdt_wbtc_component,
|
|
||||||
token_in: usdt_address,
|
|
||||||
token_out: wbtc_address.clone(),
|
|
||||||
split: 0f64,
|
|
||||||
};
|
|
||||||
|
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
|
||||||
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
|
||||||
TychoCoreChain::Ethereum.into(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let initial_encoded_swap = encoder
|
|
||||||
.encode_swap(initial_swap, context.clone())
|
|
||||||
.unwrap();
|
|
||||||
let second_encoded_swap = encoder
|
|
||||||
.encode_swap(second_swap, context)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let combined_hex =
|
|
||||||
format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap));
|
|
||||||
|
|
||||||
println!("test_encode_uniswap_v4_sequential_swap: {}", combined_hex);
|
|
||||||
assert_eq!(
|
|
||||||
combined_hex,
|
|
||||||
String::from(concat!(
|
|
||||||
// group_token in
|
|
||||||
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
|
||||||
// group_token out
|
|
||||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
|
||||||
// zero for one
|
|
||||||
"01",
|
|
||||||
// transfer type
|
|
||||||
"00",
|
|
||||||
// receiver
|
|
||||||
"cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2",
|
|
||||||
// pool params:
|
|
||||||
// - intermediary token USDT
|
|
||||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
|
||||||
// - fee
|
|
||||||
"000064",
|
|
||||||
// - tick spacing
|
|
||||||
"000001",
|
|
||||||
// - intermediary token WBTC
|
|
||||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
|
||||||
// - fee
|
|
||||||
"000bb8",
|
|
||||||
// - tick spacing
|
|
||||||
"00003c"
|
|
||||||
))
|
|
||||||
);
|
|
||||||
println!("{}", combined_hex)
|
|
||||||
}
|
|
||||||
|
|
||||||
mod ekubo {
|
mod ekubo {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user