diff --git a/config/test_executor_addresses.json b/config/test_executor_addresses.json index 018a56b..8c6dc5c 100644 --- a/config/test_executor_addresses.json +++ b/config/test_executor_addresses.json @@ -7,7 +7,7 @@ "pancakeswap_v3": "0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9", "uniswap_v4": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", "vm:balancer_v2": "0xc7183455a4C133Ae270771860664b6B7ec320bB1", - "ekubo_v2": "0x3D7Ebc40AF7092E3F1C81F2e996cbA5Cae2090d7", + "ekubo_v2": "0xa0Cb889707d426A7A386870A03bc70d1b0697598", "vm:curve": "0x1d1499e622D69689cdf9004d05Ec547d650Ff211" } } diff --git a/foundry/test/TychoRouterProtocolIntegration.t.sol b/foundry/test/TychoRouterProtocolIntegration.t.sol index 238b4f2..331ef7c 100644 --- a/foundry/test/TychoRouterProtocolIntegration.t.sol +++ b/foundry/test/TychoRouterProtocolIntegration.t.sol @@ -28,7 +28,31 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 97191013220606467325121599); + assertEq(balanceAfter - balanceBefore, 123172000092711286554274694); + } + + function testMultiProtocolIntegration() public { + // Test created with calldata from our router encoder. + // + // DAI ─(USV2)─> WETH ─(bal)─> WBTC ─(curve)─> USDT ─(ekubo)─> ETH ─(USV4)─> USDC + + deal(DAI_ADDR, ALICE, 1500 ether); + uint256 balanceBefore = address(ALICE).balance; + + // Approve permit2 + vm.startPrank(ALICE); + IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); + // Encoded solution generated using `test_multi_protocol` + (bool success,) = tychoRouterAddr.call( + hex"51bcc7b600000000000000000000000000000000000000000000005150ae84a8cdf000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2958f36da71a9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000005150ae84a8cdf0000000000000000000000000000000000000000000000000000000000000682f990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006808130800000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000414e46e936cfd0f718a485f27c233cb85a64ab162edca753cbc7c9d1bc393a688275dc15bd930e210af2e5dd8e8d8f90ec8438b821297c469d80712aadcff73b071c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021400525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501020072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e3ede3eca2a72b3aecc820e955b36f38437d01395010500691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae4603010001053ede3eca2a72b3aecc820e955b36f38437d013950071a0cb889707d426a7a386870a03bc70d1b0697598003ede3eca2a72b3aecc820e955b36f38437d01395dac17f958d2ee523a2206206994597c13d831ec7a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001a36e2eb1c43200000032006cf62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c000000000000000000000000" + ); + + vm.stopPrank(); + + uint256 balanceAfter = address(ALICE).balance; + + assertTrue(success, "Call Failed"); + assertEq(balanceAfter - balanceBefore, 732214216964381330); } function testSingleUSV4IntegrationInputETH() public { @@ -43,7 +67,7 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { // Encoded solution generated using `test_single_encoding_strategy_usv4_eth_in` (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006828a8d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680122e1000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041b7928a6257d4f01539c357c322036b5df1799313f83a119c843a239ca474955820f791f028fa10a9fe3ec0d6be7d782e5824ac1942e27ebd2a0a3e1687bec4451c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000" + hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000007e0a55d4322a6e93c2379c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f92ce00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068080cd600000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041006930677d9715fb8c55f73546d3aaff4176ee1342b9b7ae34431a4356fc98a915f3103639d8e34cbaa591a3493e887dad6e816228200dee0a693408b4fa6fdc1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cf62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000000000000000000000000000000000000000" ); vm.stopPrank(); @@ -51,7 +75,7 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 242373460199848577067005852); + assertEq(balanceAfter - balanceBefore, 235610487387677804636755778); } function testSingleUSV4IntegrationOutputETH() public { @@ -79,17 +103,10 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { assertTrue(success, "Call Failed"); console.logUint(balanceAfter - balanceBefore); - assertEq(balanceAfter - balanceBefore, 1117254495486192350); + assertEq(balanceAfter - balanceBefore, 1474406268748155809); } 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); @@ -99,7 +116,7 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { vm.startPrank(ALICE); // Encoded solution generated using `test_single_encoding_strategy_ekubo` (bool success,) = address(tychoRouter).call{value: 1 ether}( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000713d7ebc40af7092e3f1c81f2e996cba5cae2090d705cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000000000000000000000000000000000" + hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000071a0cb889707d426a7a386870a03bc70d1b069759805cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000000000000000000000000000000000" ); uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); @@ -120,7 +137,7 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { ); assertTrue(success, "Call Failed"); - assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 4691958787921); + assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 2877855391767); vm.stopPrank(); } diff --git a/foundry/test/TychoRouterSequentialSwap.t.sol b/foundry/test/TychoRouterSequentialSwap.t.sol index 88fef17..2530a0a 100644 --- a/foundry/test/TychoRouterSequentialSwap.t.sol +++ b/foundry/test/TychoRouterSequentialSwap.t.sol @@ -70,7 +70,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { ); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, 2644659787); + assertEq(usdcBalance, 2005810530); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -95,7 +95,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { ); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, 2644659787); + assertEq(usdcBalance, 2005810530); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -161,7 +161,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { vm.expectRevert( abi.encodeWithSelector( TychoRouter__NegativeSlippage.selector, - 2644659787, // actual amountOut + 2005810530, // actual amountOut minAmountOut ) ); @@ -234,7 +234,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { "", pleEncode(swaps) ); - uint256 expectedAmount = 2644659787; + uint256 expectedAmount = 2005810530; assertEq(amountOut, expectedAmount); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); assertEq(usdcBalance, expectedAmount); @@ -295,7 +295,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { pleEncode(swaps) ); - uint256 expectedAmount = 1111174255471849849; // 1.11 ETH + uint256 expectedAmount = 1466332452295613768; // 1.11 ETH assertEq(amountOut, expectedAmount); assertEq(ALICE.balance, expectedAmount); @@ -338,7 +338,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { ); tychoRouter.exposedSequentialSwap(amountIn, pleEncode(swaps)); - assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99889294); + assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99792554); } function testSequentialSwapIntegrationPermit2() public { @@ -361,7 +361,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2552915143); + assertEq(balanceAfter - balanceBefore, 1951856272); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -385,11 +385,12 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2552915143); + assertEq(balanceAfter - balanceBefore, 1951856272); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } function testSequentialCyclicSwapIntegration() public { + // USDC -> WETH -> USDC using two pools deal(USDC_ADDR, ALICE, 100 * 10 ** 6); // Approve permit2 @@ -397,11 +398,11 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_sequential_strategy_cyclic_swap` (bool success,) = tychoRouterAddr.call( - hex"51bcc7b60000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682dbba300000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680635ab00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041adc1487dd76b622c3762cfeb017fc51d2e3513e8e2e2a6a8d8e153d79192474735457ed064158c007ffc2a42cc8ee7ccc256155dbe4ef3b5404c4addbeb5612a1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640010200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000000000" + hex"51bcc7b60000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ec8f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682f96a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680810ab00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000415de1a1f5644d780aa3e22af583e87639ff7d519518576da5b10c15748d75d7f64b9d4fc2439869fc226ca4a8b69c6cc4b284427b0d5d73c72e54f115cdf2bbca1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640010200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000000000" ); assertTrue(success, "Call Failed"); - assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99889294); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99792554); vm.stopPrank(); } @@ -426,7 +427,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2554299052); + assertEq(balanceAfter - balanceBefore, 1952973189); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -450,7 +451,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2647438249); + assertEq(balanceAfter - balanceBefore, 2015740345); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -474,7 +475,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDT_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2650183330); + assertEq(balanceAfter - balanceBefore, 2018869128); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -498,7 +499,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2549391308); + assertEq(balanceAfter - balanceBefore, 1949668893); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } } diff --git a/foundry/test/TychoRouterSingleSwap.t.sol b/foundry/test/TychoRouterSingleSwap.t.sol index 1a374c7..16b7f0c 100644 --- a/foundry/test/TychoRouterSingleSwap.t.sol +++ b/foundry/test/TychoRouterSingleSwap.t.sol @@ -36,7 +36,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { amountIn, WETH_ADDR, DAI_ADDR, - 2659881924818443699786, + 2008817438608734439722, false, false, ALICE, @@ -46,7 +46,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { ); uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE); - assertEq(daiBalance, 2659881924818443699787); + assertEq(daiBalance, 2018817438608734439722); assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 0); vm.stopPrank(); @@ -73,7 +73,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory swap = encodeSingleSwap(address(usv2Executor), protocolData); - uint256 minAmountOut = 2600 * 1e18; + uint256 minAmountOut = 2000 * 1e18; uint256 amountOut = tychoRouter.singleSwap( amountIn, WETH_ADDR, @@ -85,7 +85,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { swap ); - uint256 expectedAmount = 2659881924818443699787; + uint256 expectedAmount = 2018817438608734439722; assertEq(amountOut, expectedAmount); uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE); assertEq(daiBalance, expectedAmount); @@ -180,7 +180,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { vm.expectRevert( abi.encodeWithSelector( TychoRouter__NegativeSlippage.selector, - 2659881924818443699787, // actual amountOut + 2018817438608734439722, // actual amountOut minAmountOut ) ); @@ -236,7 +236,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { "", swap ); - uint256 expectedAmount = 2659881924818443699787; + uint256 expectedAmount = 2018817438608734439722; assertEq(amountOut, expectedAmount); uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE); assertEq(daiBalance, expectedAmount); @@ -280,7 +280,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { swap ); - uint256 expectedAmount = 1120007305574805922; + uint256 expectedAmount = 1475644707225677606; assertEq(amountOut, expectedAmount); assertEq(ALICE.balance, expectedAmount); @@ -296,14 +296,14 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); // Encoded solution generated using `test_single_swap_strategy_encoder_no_permit2` (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200010000000000000000000000000000" + hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200010000000000000000000000000000" ); vm.stopPrank(); uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2659881924818443699787); + assertEq(balanceAfter - balanceBefore, 2018817438608734439722); } function testSingleSwapIntegrationPermit2() public { @@ -315,14 +315,14 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_single_swap_strategy_encoder` (bool success,) = tychoRouterAddr.call( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200020000000000000000000000000000" + hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006b56051582a970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f946a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068080e7200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041c0ace69971589bd5136c309c83a06d60a7a54a49a2f1cecdf51cc5aecd4f7cce07a1b4a152d758fb6c3e4a73f8cf96ca3b3e8ab82b402733b7979a67021e99a51c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200020000000000000000000000000000" ); vm.stopPrank(); uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2659881924818443699787); + assertEq(balanceAfter - balanceBefore, 2018817438608734439722); } function testSingleSwapWithWrapIntegration() public { @@ -335,7 +335,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { vm.startPrank(ALICE); // Encoded solution generated using `test_single_swap_strategy_encoder_wrap` (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682db3ee00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068062df600000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412bda9e4c6208c6851db4a383761f0511ace6a071dafcb8c017f312777d11988f50d017cc914ea2db8a8082a469584bff851efc00533b803fcc1aa4ada81c6c9e1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" + hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000059fb7d3830e6fc064b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f965f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006808106700000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041cdef1c27d45a13adde80b5d93c8786741b69ddbe7684c4356f3dc7d4aa8029cb3cba0aac801787a7993ba0be72a6b459fa2a5c18a8e4938a0ccd3503d1be81841c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" ); vm.stopPrank(); @@ -343,7 +343,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2659881924818443699787); + assertEq(balanceAfter - balanceBefore, 2018817438608734439722); } function testSingleSwapWithUnwrapIntegration() public { @@ -365,6 +365,6 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { uint256 balanceAfter = ALICE.balance; assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 1120007305574805922); + assertEq(balanceAfter - balanceBefore, 1475644707225677606); } } diff --git a/foundry/test/TychoRouterSplitSwap.t.sol b/foundry/test/TychoRouterSplitSwap.t.sol index b26e16e..0f8b678 100644 --- a/foundry/test/TychoRouterSplitSwap.t.sol +++ b/foundry/test/TychoRouterSplitSwap.t.sol @@ -93,7 +93,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { vm.stopPrank(); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, 2615491639); + assertEq(usdcBalance, 1989737355); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -126,7 +126,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { ); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, 2615491639); + assertEq(usdcBalance, 1989737355); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -153,7 +153,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { ); uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, 2615491639); + assertEq(usdcBalance, 1989737355); assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 0); } @@ -226,7 +226,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { vm.expectRevert( abi.encodeWithSelector( TychoRouter__NegativeSlippage.selector, - 2615491639, // actual amountOut + 1989737355, // actual amountOut minAmountOut ) ); @@ -283,7 +283,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { amountIn, address(0), DAI_ADDR, - 2659881924818443699780, + 2008817438608734439722, true, false, 2, @@ -292,7 +292,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { "", pleEncode(swaps) ); - uint256 expectedAmount = 2659881924818443699787; + uint256 expectedAmount = 2018817438608734439722; assertEq(amountOut, expectedAmount); uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE); assertEq(daiBalance, expectedAmount); @@ -332,7 +332,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { amountIn, DAI_ADDR, address(0), - 1120007305574805920, + 1465644707225677606, false, true, 2, @@ -342,7 +342,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { pleEncode(swaps) ); - uint256 expectedAmount = 1120007305574805922; // 1.12 ETH + uint256 expectedAmount = 1475644707225677606; // 1.12 ETH assertEq(amountOut, expectedAmount); assertEq(ALICE.balance, expectedAmount); @@ -453,7 +453,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { pleEncode(swaps) ); - assertEq(IERC20(USDT_ADDR).balanceOf(ALICE), 99943852); + assertEq(IERC20(USDT_ADDR).balanceOf(ALICE), 99963618); vm.stopPrank(); } @@ -494,7 +494,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps)); - assertEq(IERC20(WBTC_ADDR).balanceOf(ALICE), 102718); + assertEq(IERC20(WBTC_ADDR).balanceOf(ALICE), 118281); } function testSplitInputCyclicSwapInternalMethod() public { @@ -564,7 +564,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { ); tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps)); vm.stopPrank(); - assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99574171); + assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99654537); } function testSplitOutputCyclicSwapInternalMethod() public { @@ -629,7 +629,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { ); tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps)); - assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99525908); + assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99444510); } // Base Network Tests @@ -699,7 +699,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { ); assertTrue(success, "Call Failed"); - assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99574171); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99654537); vm.stopPrank(); } @@ -712,11 +712,11 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_split_output_cyclic_swap` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000" + hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005e703f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682f963200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006808103a0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c46b497d6f01110f05257114b978d2fd2d493ac8dae2c7892bbfa593fc5d062384590828248348fe87b234c3417e463f12d4732e287a56882841a92bc41e9121b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000" ); assertTrue(success, "Call Failed"); - assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99525908); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99444510); vm.stopPrank(); } diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index c97cb56..de68184 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -55,7 +55,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper { MockERC20[] tokens; function setUp() public { - uint256 forkBlock = 21817316; + uint256 forkBlock = 22082754; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); vm.startPrank(ADMIN); diff --git a/src/encoding/evm/constants.rs b/src/encoding/evm/constants.rs index d4a4863..37d8aff 100644 --- a/src/encoding/evm/constants.rs +++ b/src/encoding/evm/constants.rs @@ -42,5 +42,7 @@ pub static CALLBACK_CONSTRAINED_PROTOCOLS: LazyLock> = Laz let mut set = HashSet::new(); set.insert("uniswap_v3"); set.insert("pancakeswap_v3"); + set.insert("uniswap_v4"); + set.insert("ekubo_v2"); set }); diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 7dd7afd..a9599c7 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -701,16 +701,16 @@ mod tests { U256::from_str("2659881924818443699787").unwrap(), )] #[case::no_check_with_slippage( - Some(BigUint::from_str("3_000_000000000000000000").unwrap()), + Some(BigUint::from_str("2_000_000000000000000000").unwrap()), Some(0.01f64), None, - U256::from_str("2_970_000000000000000000").unwrap(), + U256::from_str("1_980_000000000000000000").unwrap(), )] #[case::with_check_and_slippage( - Some(BigUint::from_str("3_000_000000000000000000").unwrap()), + Some(BigUint::from_str("2_000_000000000000000000").unwrap()), Some(0.01f64), - Some(BigUint::from_str("2_999_000000000000000000").unwrap()), - U256::from_str("2_999_000000000000000000").unwrap(), + Some(BigUint::from_str("1_999_000000000000000000").unwrap()), + U256::from_str("1_999_000000000000000000").unwrap(), )] fn test_single_swap_strategy_encoder( #[case] expected_amount: Option, @@ -806,10 +806,10 @@ mod tests { let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap(); let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap(); - let expected_amount = Some(BigUint::from_str("2_650_000000000000000000").unwrap()); + let expected_amount = Some(BigUint::from_str("1_650_000000000000000000").unwrap()); let slippage = Some(0.01f64); - let checked_amount = Some(BigUint::from_str("2_640_000000000000000000").unwrap()); - let expected_min_amount = U256::from_str("2_640_000000000000000000").unwrap(); + let checked_amount = Some(BigUint::from_str("1_640_000000000000000000").unwrap()); + let expected_min_amount = U256::from_str("1_640_000000000000000000").unwrap(); let swap = Swap { component: ProtocolComponent { @@ -912,7 +912,7 @@ mod tests { given_amount: BigUint::from_str("1_000000000000000000").unwrap(), checked_token: dai, expected_amount: None, - checked_amount: Some(BigUint::from_str("2659881924818443699787").unwrap()), + checked_amount: Some(BigUint::from_str("1659881924818443699787").unwrap()), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), swaps: vec![swap], @@ -1213,7 +1213,7 @@ mod tests { given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals) checked_token: usdc.clone(), expected_amount: None, - checked_amount: Some(BigUint::from_str("99889294").unwrap()), /* Expected output + checked_amount: Some(BigUint::from_str("99389294").unwrap()), /* Expected output * from * test */ slippage: None, @@ -1232,7 +1232,7 @@ mod tests { "0000000000000000000000000000000000000000000000000000000005f5e100", // given amount "000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // given token "000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // checked token - "0000000000000000000000000000000000000000000000000000000005f4308e", // min amount out + "0000000000000000000000000000000000000000000000000000000005ec8f6e", // min amount out "0000000000000000000000000000000000000000000000000000000000000000", // wrap action "0000000000000000000000000000000000000000000000000000000000000000", // unwrap action "000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver @@ -1576,6 +1576,154 @@ mod tests { let _hex_calldata = encode(&calldata); println!("test_balancer_v2_uniswap_v2: {}", _hex_calldata); } + + #[test] + fn test_multi_protocol() { + // Note: This test does not assert anything. It is only used to obtain integration + // test data for our router solidity test. + // + // Performs the following swap: + // + // DAI ─(USV2)-> WETH ─(bal)─> WBTC ─(curve)─> USDT ─(ekubo)─> USDC ─(USV4)─> ETH + + let weth = weth(); + let eth = eth(); + let wbtc = Bytes::from_str("0x2260fac5e5542a773aa44fbcfedf7c193bc2c599").unwrap(); + let usdc = Bytes::from_str("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap(); + let usdt = Bytes::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(); + let dai = Bytes::from_str("0x6B175474E89094C44Da98b954EedeAC495271d0F").unwrap(); + + // Set up a mock private key for signing (Alice's pk in our router tests) + let private_key = + "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234" + .to_string(); + + let usv2_swap_dai_weth = Swap { + component: ProtocolComponent { + id: "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: dai.clone(), + token_out: weth.clone(), + split: 0f64, + }; + + let balancer_swap_weth_wbtc = Swap { + component: ProtocolComponent { + id: "0xa6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e" + .to_string(), + protocol_system: "vm:balancer_v2".to_string(), + ..Default::default() + }, + token_in: weth.clone(), + token_out: wbtc.clone(), + split: 0f64, + }; + + let curve_swap_wbtc_usdt = Swap { + component: ProtocolComponent { + id: String::from("0xD51a44d3FaE010294C616388b506AcdA1bfAAE46"), + protocol_system: String::from("vm:curve"), + static_attributes: { + let mut attrs: HashMap = HashMap::new(); + attrs.insert( + "factory".into(), + Bytes::from( + "0x0000000000000000000000000000000000000000" + .as_bytes() + .to_vec(), + ), + ); + attrs + }, + ..Default::default() + }, + token_in: wbtc.clone(), + token_out: usdt.clone(), + split: 0f64, + }; + + // Ekubo + + let component = ProtocolComponent { + // All Ekubo swaps go through the core contract - not necessary to specify pool + // id for test + protocol_system: "ekubo_v2".to_string(), + // 0.0025% fee & 0.005% base pool + static_attributes: HashMap::from([ + ("fee".to_string(), Bytes::from(461168601842738_u64)), + ("tick_spacing".to_string(), Bytes::from(50_u32)), + ("extension".to_string(), Bytes::zero(20)), + ]), + ..Default::default() + }; + let ekubo_swap_usdt_usdc = Swap { + component, + token_in: usdt.clone(), + token_out: usdc.clone(), + split: 0f64, + }; + + // USV4 + // Fee and tick spacing information for this test is obtained by querying the + // USV4 Position Manager contract: 0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e + // Using the poolKeys function with the first 25 bytes of the pool id + let pool_fee_usdc_eth = Bytes::from(BigInt::from(3000).to_signed_bytes_be()); + let tick_spacing_usdc_eth = Bytes::from(BigInt::from(60).to_signed_bytes_be()); + let mut static_attributes_usdc_eth: HashMap = HashMap::new(); + static_attributes_usdc_eth.insert("key_lp_fee".into(), pool_fee_usdc_eth); + static_attributes_usdc_eth.insert("tick_spacing".into(), tick_spacing_usdc_eth); + + let usv4_swap_usdc_eth = Swap { + component: ProtocolComponent { + id: "0xdce6394339af00981949f5f3baf27e3610c76326a700af57e4b3e3ae4977f78d" + .to_string(), + protocol_system: "uniswap_v4".to_string(), + static_attributes: static_attributes_usdc_eth, + ..Default::default() + }, + token_in: usdc.clone(), + token_out: eth.clone(), + split: 0f64, + }; + + // Put all components together + let swap_encoder_registry = get_swap_encoder_registry(); + let encoder = SequentialSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), + ) + .unwrap(); + let solution = Solution { + exact_out: false, + given_token: dai, + given_amount: BigUint::from_str("1500_000000000000000000").unwrap(), + checked_token: eth, + expected_amount: None, + checked_amount: Some(BigUint::from_str("732214216964381330").unwrap()), + sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2") + .unwrap(), + swaps: vec![ + usv2_swap_dai_weth, + balancer_swap_weth_wbtc, + curve_swap_wbtc_usdt, + ekubo_swap_usdt_usdc, + usv4_swap_usdc_eth, + ], + ..Default::default() + }; + + let (calldata, _) = encoder + .encode_strategy(solution) + .unwrap(); + + let _hex_calldata = encode(&calldata); + println!("multi_protocol: {}", _hex_calldata); + } } } @@ -1932,7 +2080,7 @@ mod tests { given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals) checked_token: usdc.clone(), expected_amount: None, - checked_amount: Some(BigUint::from_str("99525908").unwrap()), /* Expected output + checked_amount: Some(BigUint::from_str("99025908").unwrap()), /* Expected output * from * test */ sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), @@ -1952,7 +2100,7 @@ mod tests { "0000000000000000000000000000000000000000000000000000000005f5e100", // given amount "000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // given token "000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // checked token - "0000000000000000000000000000000000000000000000000000000005eea514", // min amount out + "0000000000000000000000000000000000000000000000000000000005e703f4", // min amount out "0000000000000000000000000000000000000000000000000000000000000000", // wrap action "0000000000000000000000000000000000000000000000000000000000000000", // unwrap action "0000000000000000000000000000000000000000000000000000000000000002", // tokens length @@ -2057,7 +2205,7 @@ mod tests { given_amount: BigUint::from_str("1_000000000000000000").unwrap(), checked_token: token_out, expected_amount: None, - checked_amount: Some(BigUint::from_str("1").unwrap()), + checked_amount: Some(BigUint::from_str("1000").unwrap()), slippage: None, // Alice sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), @@ -2122,7 +2270,7 @@ mod tests { given_amount: BigUint::from_str("1_000000000000000000").unwrap(), checked_token: pepe, expected_amount: None, - checked_amount: Some(BigUint::from_str("242373460199848577067005852").unwrap()), + checked_amount: Some(BigUint::from_str("152373460199848577067005852").unwrap()), slippage: None, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),