From 4f9785fdacb309feb689abc874f458eb06540a1b Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Fri, 18 Apr 2025 16:23:03 -0400 Subject: [PATCH 1/6] fix: Configurable fee on USV2 executor. - This fee is not the same depending on the fork. For example, Pancake V2 uses a 0.25% fee, while the USV2 fee is 0.3%. We were wrongly hard-coding this fee to 0.3%. --- foundry/scripts/deploy-executors.js | 35 +++++++++++-------- foundry/src/executors/UniswapV2Executor.sol | 12 +++++-- foundry/test/TychoRouterTestSetup.sol | 2 +- .../test/executors/UniswapV2Executor.t.sol | 12 ++++--- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/foundry/scripts/deploy-executors.js b/foundry/scripts/deploy-executors.js index 7149d63..9aa242f 100644 --- a/foundry/scripts/deploy-executors.js +++ b/foundry/scripts/deploy-executors.js @@ -5,25 +5,28 @@ const hre = require("hardhat"); // Comment out the executors you don't want to deploy const executors_to_deploy = { "ethereum": [ - // USV2 - Args: Factory, Pool Init Code Hash + // USV2 - Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", - "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" + "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f", + 30 ] }, - // SUSHISWAP - Args: Factory, Pool Init Code Hash + // SUSHISWAP - Args: Factory, Pool Init Code Hash, Fee BPS, Fee BPS { exchange: "UniswapV2Executor", args: [ "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac", - "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303" + "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303", + 30 ] }, - // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash + // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x1097053Fd2ea711dad45caCcc45EfF7548fCB362", - "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d" + "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d", + 25 ] }, // USV3 -Args: Factory, Pool Init Code Hash @@ -57,25 +60,28 @@ const executors_to_deploy = { } ], "base": [ - // Args: Factory, Pool Init Code Hash + // Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6", - "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" + "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f", + 30 ] }, - // SUSHISWAP V2 - Args: Factory, Pool Init Code Hash + // SUSHISWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x71524B4f93c58fcbF659783284E38825f0622859", - "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303" + "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303", + 30 ] }, - // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash + // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", - "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d" + "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d", + 25 ] }, // USV3 - Args: Factory, Pool Init Code Hash @@ -97,11 +103,12 @@ const executors_to_deploy = { {exchange: "BalancerV2Executor", args: []}, ], "unichain": [ - // Args: Factory, Pool Init Code Hash + // Args: Factory, Pool Init Code Hash, Fee BPS { exchange: "UniswapV2Executor", args: [ "0x1f98400000000000000000000000000000000002", - "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" + "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f", + 30 ] }, // USV3 - Args: Factory, Pool Init Code Hash diff --git a/foundry/src/executors/UniswapV2Executor.sol b/foundry/src/executors/UniswapV2Executor.sol index 863216d..ce172a7 100644 --- a/foundry/src/executors/UniswapV2Executor.sol +++ b/foundry/src/executors/UniswapV2Executor.sol @@ -10,6 +10,7 @@ error UniswapV2Executor__InvalidDataLength(); error UniswapV2Executor__InvalidTarget(); error UniswapV2Executor__InvalidFactory(); error UniswapV2Executor__InvalidInitCode(); +error UniswapV2Executor__InvalidFee(); contract UniswapV2Executor is IExecutor, TokenTransfer { using SafeERC20 for IERC20; @@ -17,8 +18,9 @@ contract UniswapV2Executor is IExecutor, TokenTransfer { address public immutable factory; bytes32 public immutable initCode; address private immutable self; + uint256 public immutable feeBps; - constructor(address _factory, bytes32 _initCode, address _permit2) + constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps) TokenTransfer(_permit2) { if (_factory == address(0)) { @@ -29,6 +31,10 @@ contract UniswapV2Executor is IExecutor, TokenTransfer { } factory = _factory; initCode = _initCode; + if (_feeBps > 10000) { + revert UniswapV2Executor__InvalidFee(); + } + feeBps = _feeBps; self = address(this); } @@ -100,9 +106,9 @@ contract UniswapV2Executor is IExecutor, TokenTransfer { } require(reserveIn > 0 && reserveOut > 0, "L"); - uint256 amountInWithFee = amountIn * 997; + uint256 amountInWithFee = amountIn * (10000 - feeBps); uint256 numerator = amountInWithFee * uint256(reserveOut); - uint256 denominator = (uint256(reserveIn) * 1000) + amountInWithFee; + uint256 denominator = (uint256(reserveIn) * 10000) + amountInWithFee; amount = numerator / denominator; } diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index c97cb56..0252c2b 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -99,7 +99,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper { IPoolManager poolManager = IPoolManager(poolManagerAddress); usv2Executor = - new UniswapV2Executor(factoryV2, initCodeV2, PERMIT2_ADDRESS); + new UniswapV2Executor(factoryV2, initCodeV2, PERMIT2_ADDRESS, 30); usv3Executor = new UniswapV3Executor(factoryV3, initCodeV3, PERMIT2_ADDRESS); usv4Executor = new UniswapV4Executor(poolManager, PERMIT2_ADDRESS); diff --git a/foundry/test/executors/UniswapV2Executor.t.sol b/foundry/test/executors/UniswapV2Executor.t.sol index 64be1d2..70f16c8 100644 --- a/foundry/test/executors/UniswapV2Executor.t.sol +++ b/foundry/test/executors/UniswapV2Executor.t.sol @@ -8,8 +8,8 @@ import {Constants} from "../Constants.sol"; import {Permit2TestHelper} from "../Permit2TestHelper.sol"; contract UniswapV2ExecutorExposed is UniswapV2Executor { - constructor(address _factory, bytes32 _initCode, address _permit2) - UniswapV2Executor(_factory, _initCode, _permit2) + constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps) + UniswapV2Executor(_factory, _initCode, _permit2, _feeBps) {} function decodeParams(bytes calldata data) @@ -63,17 +63,19 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper { uint256 forkBlock = 17323404; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); uniswapV2Exposed = new UniswapV2ExecutorExposed( - USV2_FACTORY_ETHEREUM, USV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS + USV2_FACTORY_ETHEREUM, USV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS, 30 ); sushiswapV2Exposed = new UniswapV2ExecutorExposed( SUSHISWAPV2_FACTORY_ETHEREUM, SUSHIV2_POOL_CODE_INIT_HASH, - PERMIT2_ADDRESS + PERMIT2_ADDRESS, + 30 ); pancakeswapV2Exposed = new UniswapV2ExecutorExposed( PANCAKESWAPV2_FACTORY_ETHEREUM, PANCAKEV2_POOL_CODE_INIT_HASH, - PERMIT2_ADDRESS + PERMIT2_ADDRESS, + 25 ); permit2 = IAllowanceTransfer(PERMIT2_ADDRESS); } From af68016223cb74b4896ae627be798e6d211ef4e6 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Tue, 22 Apr 2025 17:45:56 -0400 Subject: [PATCH 2/6] fix: Tighten max feeBps in USV2 executor Value was too lenient. We are assuming no forks will have higher fees than the original USV2. --- foundry/src/executors/UniswapV2Executor.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundry/src/executors/UniswapV2Executor.sol b/foundry/src/executors/UniswapV2Executor.sol index ce172a7..518b761 100644 --- a/foundry/src/executors/UniswapV2Executor.sol +++ b/foundry/src/executors/UniswapV2Executor.sol @@ -31,7 +31,7 @@ contract UniswapV2Executor is IExecutor, TokenTransfer { } factory = _factory; initCode = _initCode; - if (_feeBps > 10000) { + if (_feeBps > 30) { revert UniswapV2Executor__InvalidFee(); } feeBps = _feeBps; From 132eed4bb986983453f6e17e69d19ae93921385a Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Tue, 22 Apr 2025 01:18:19 -0400 Subject: [PATCH 3/6] test: 5-hop Multi-protocol integration test - Needed to add ekubo and uniswap v4 to callback-limited protocols. - I had to bump the fork block in all of our integration tests: The way it was before meant that certain integration tests were using certain executor addresses, and others were using different ones, because of the redeployment. This was a pain to account for on the rust side. Instead, all tests now use an Ekubo-compatible fork block. Values needed to be updated because of price changes between blocks. --- config/test_executor_addresses.json | 2 +- .../test/TychoRouterProtocolIntegration.t.sol | 43 +++-- foundry/test/TychoRouterSequentialSwap.t.sol | 29 +-- foundry/test/TychoRouterSingleSwap.t.sol | 28 +-- foundry/test/TychoRouterSplitSwap.t.sol | 30 +-- foundry/test/TychoRouterTestSetup.sol | 2 +- src/encoding/evm/constants.rs | 2 + .../evm/strategy_encoder/strategy_encoders.rs | 178 ++++++++++++++++-- 8 files changed, 241 insertions(+), 73 deletions(-) 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(), From d5d6e37041c316c460a3cf216c71eae1987a953f Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Tue, 22 Apr 2025 17:50:09 -0400 Subject: [PATCH 4/6] fix: Changes after rebase --- foundry/src/executors/UniswapV2Executor.sol | 9 ++++++--- foundry/test/executors/UniswapV2Executor.t.sol | 13 ++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/foundry/src/executors/UniswapV2Executor.sol b/foundry/src/executors/UniswapV2Executor.sol index 518b761..dd04dd1 100644 --- a/foundry/src/executors/UniswapV2Executor.sol +++ b/foundry/src/executors/UniswapV2Executor.sol @@ -20,9 +20,12 @@ contract UniswapV2Executor is IExecutor, TokenTransfer { address private immutable self; uint256 public immutable feeBps; - constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps) - TokenTransfer(_permit2) - { + constructor( + address _factory, + bytes32 _initCode, + address _permit2, + uint256 _feeBps + ) TokenTransfer(_permit2) { if (_factory == address(0)) { revert UniswapV2Executor__InvalidFactory(); } diff --git a/foundry/test/executors/UniswapV2Executor.t.sol b/foundry/test/executors/UniswapV2Executor.t.sol index 70f16c8..ea0d825 100644 --- a/foundry/test/executors/UniswapV2Executor.t.sol +++ b/foundry/test/executors/UniswapV2Executor.t.sol @@ -8,9 +8,12 @@ import {Constants} from "../Constants.sol"; import {Permit2TestHelper} from "../Permit2TestHelper.sol"; contract UniswapV2ExecutorExposed is UniswapV2Executor { - constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps) - UniswapV2Executor(_factory, _initCode, _permit2, _feeBps) - {} + constructor( + address _factory, + bytes32 _initCode, + address _permit2, + uint256 _feeBps + ) UniswapV2Executor(_factory, _initCode, _permit2, _feeBps) {} function decodeParams(bytes calldata data) external @@ -69,13 +72,13 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper { SUSHISWAPV2_FACTORY_ETHEREUM, SUSHIV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS, - 30 + 30 ); pancakeswapV2Exposed = new UniswapV2ExecutorExposed( PANCAKESWAPV2_FACTORY_ETHEREUM, PANCAKEV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS, - 25 + 25 ); permit2 = IAllowanceTransfer(PERMIT2_ADDRESS); } From 02cbb67b3844a674fc52457967d123566fa77bf4 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Wed, 23 Apr 2025 09:57:23 +0100 Subject: [PATCH 5/6] fix: After merge test fixes Took 11 minutes --- foundry/test/TychoRouterSingleSwap.t.sol | 4 ++-- src/encoding/evm/strategy_encoder/strategy_encoders.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/foundry/test/TychoRouterSingleSwap.t.sol b/foundry/test/TychoRouterSingleSwap.t.sol index b77e67e..b0fe140 100644 --- a/foundry/test/TychoRouterSingleSwap.t.sol +++ b/foundry/test/TychoRouterSingleSwap.t.sol @@ -376,13 +376,13 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { vm.startPrank(ALICE); // Encoded solution generated using `test_single_swap_strategy_encoder_no_transfer_in` (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" + hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" ); vm.stopPrank(); uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE); assertTrue(success, "Call Failed"); - assertEq(balanceAfter - balanceBefore, 2659881924818443699787); + assertEq(balanceAfter - balanceBefore, 2018817438608734439722); } } diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 1148585..40fa2ef 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -873,10 +873,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 { @@ -1772,6 +1772,7 @@ mod tests { swap_encoder_registry, Some(private_key), Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), + false, ) .unwrap(); let solution = Solution { From 48565f3460295adb2eaba59433caa0a821d03409 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 23 Apr 2025 08:43:18 +0000 Subject: [PATCH 6/6] chore(release): 1.0.1 [skip ci] ## [1.0.1](https://github.com/propeller-heads/tycho-execution/compare/1.0.0...1.0.1) (2025-04-23) ### Bug Fixes * Changes after rebase ([d39a2ac](https://github.com/propeller-heads/tycho-execution/commit/d39a2accce2d533f8d26223156853b442c02355b)) * Configurable fee on USV2 executor. ([826aa54](https://github.com/propeller-heads/tycho-execution/commit/826aa54631b71fd209c6cc56c90dc373a4da966d)) * Tighten max feeBps in USV2 executor ([e07573b](https://github.com/propeller-heads/tycho-execution/commit/e07573bbb8db7ab5c88728dcaea8f537bc2520d4)) --- CHANGELOG.md | 9 +++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb54b2..eb25ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [1.0.1](https://github.com/propeller-heads/tycho-execution/compare/1.0.0...1.0.1) (2025-04-23) + + +### Bug Fixes + +* Changes after rebase ([d39a2ac](https://github.com/propeller-heads/tycho-execution/commit/d39a2accce2d533f8d26223156853b442c02355b)) +* Configurable fee on USV2 executor. ([826aa54](https://github.com/propeller-heads/tycho-execution/commit/826aa54631b71fd209c6cc56c90dc373a4da966d)) +* Tighten max feeBps in USV2 executor ([e07573b](https://github.com/propeller-heads/tycho-execution/commit/e07573bbb8db7ab5c88728dcaea8f537bc2520d4)) + ## [1.0.0](https://github.com/propeller-heads/tycho-execution/compare/0.81.0...1.0.0) (2025-04-22) diff --git a/Cargo.lock b/Cargo.lock index 82d6d4b..372c275 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4341,7 +4341,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "1.0.0" +version = "1.0.1" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index f8c8b8e..15dc129 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "1.0.0" +version = "1.0.1" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution"