From 299126da160b9ce45c3cbc7cef080c17eaad4a39 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 9 Sep 2025 11:29:32 +0200 Subject: [PATCH 01/16] test: add tests to generate runtime bytecode for the executors --- foundry/test/.gitignore | 1 + foundry/test/protocols/BalancerV2.t.sol | 1 - foundry/test/protocols/BalancerV3.t.sol | 4 ++++ foundry/test/protocols/Curve.t.sol | 6 +++++- foundry/test/protocols/Ekubo.t.sol | 4 ++++ foundry/test/protocols/Hashflow.t.sol | 2 +- foundry/test/protocols/MaverickV2.t.sol | 4 ++++ foundry/test/protocols/UniswapV2.t.sol | 4 ++++ foundry/test/protocols/UniswapV3.t.sol | 11 ++++++++++- foundry/test/protocols/UniswapV4.t.sol | 4 ++++ 10 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 foundry/test/.gitignore diff --git a/foundry/test/.gitignore b/foundry/test/.gitignore new file mode 100644 index 0000000..47e2914 --- /dev/null +++ b/foundry/test/.gitignore @@ -0,0 +1 @@ +*.runtime.json diff --git a/foundry/test/protocols/BalancerV2.t.sol b/foundry/test/protocols/BalancerV2.t.sol index 1540ce1..7c056f1 100644 --- a/foundry/test/protocols/BalancerV2.t.sol +++ b/foundry/test/protocols/BalancerV2.t.sol @@ -136,7 +136,6 @@ contract BalancerV2ExecutorTest is Constants, TestUtils { } function testExportContract() public { - vm.skip(true); exportRuntimeBytecode(address(balancerV2Exposed), "BalancerV2"); } } diff --git a/foundry/test/protocols/BalancerV3.t.sol b/foundry/test/protocols/BalancerV3.t.sol index 3a1a182..d28a94b 100644 --- a/foundry/test/protocols/BalancerV3.t.sol +++ b/foundry/test/protocols/BalancerV3.t.sol @@ -119,6 +119,10 @@ contract BalancerV3ExecutorTest is Constants, TestUtils { assertGt(balanceAfter, balanceBefore); assertEq(balanceAfter - balanceBefore, amountOut); } + + function testExportContract() public { + exportRuntimeBytecode(address(balancerV3Exposed), "BalancerV3"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { diff --git a/foundry/test/protocols/Curve.t.sol b/foundry/test/protocols/Curve.t.sol index bf288d4..666ca37 100644 --- a/foundry/test/protocols/Curve.t.sol +++ b/foundry/test/protocols/Curve.t.sol @@ -46,7 +46,7 @@ contract CurveExecutorExposed is CurveExecutor { } } -contract CurveExecutorTest is Test, Constants { +contract CurveExecutorTest is Test, TestUtils, Constants { using SafeERC20 for IERC20; CurveExecutorExposed curveExecutorExposed; @@ -393,6 +393,10 @@ contract CurveExecutorTest is Test, Constants { metaRegistry.get_coin_indices(pool, tokenIn, tokenOut); return (coinInIndex, coinOutIndex); } + + function testExportContract() public { + exportRuntimeBytecode(address(curveExecutorExposed), "Curve"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { diff --git a/foundry/test/protocols/Ekubo.t.sol b/foundry/test/protocols/Ekubo.t.sol index f1e5da9..04b4b18 100644 --- a/foundry/test/protocols/Ekubo.t.sol +++ b/foundry/test/protocols/Ekubo.t.sol @@ -202,6 +202,10 @@ contract EkuboExecutorTest is Constants, TestUtils { function testMultiHopSwapIntegration() public setUpFork(22082754) { multiHopSwap(loadCallDataFromFile("test_ekubo_encode_swap_multi")); } + + function testExportContract() public { + exportRuntimeBytecode(address(executor), "Ekubo"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { diff --git a/foundry/test/protocols/Hashflow.t.sol b/foundry/test/protocols/Hashflow.t.sol index dee68d8..69c03d4 100644 --- a/foundry/test/protocols/Hashflow.t.sol +++ b/foundry/test/protocols/Hashflow.t.sol @@ -41,7 +41,7 @@ contract HashflowUtils is Test { } } -contract HashflowExecutorECR20Test is Constants, HashflowUtils { +contract HashflowExecutorECR20Test is Constants, TestUtils, HashflowUtils { using SafeERC20 for IERC20; HashflowExecutorExposed executor; diff --git a/foundry/test/protocols/MaverickV2.t.sol b/foundry/test/protocols/MaverickV2.t.sol index 131994a..998a154 100644 --- a/foundry/test/protocols/MaverickV2.t.sol +++ b/foundry/test/protocols/MaverickV2.t.sol @@ -126,6 +126,10 @@ contract MaverickV2ExecutorTest is TestUtils, Constants { assertGt(balanceAfter, balanceBefore); assertEq(balanceAfter - balanceBefore, amountOut); } + + function testExportContract() public { + exportRuntimeBytecode(address(maverickV2Exposed), "MaverickV2"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { diff --git a/foundry/test/protocols/UniswapV2.t.sol b/foundry/test/protocols/UniswapV2.t.sol index a509877..4e0ec28 100644 --- a/foundry/test/protocols/UniswapV2.t.sol +++ b/foundry/test/protocols/UniswapV2.t.sol @@ -263,4 +263,8 @@ contract UniswapV2ExecutorTest is Constants, Permit2TestHelper, TestUtils { assertEq(IERC20(BASE_MAG7).balanceOf(BOB), 1379830606); } + + function testExportContract() public { + exportRuntimeBytecode(address(uniswapV2Exposed), "UniswapV2"); + } } diff --git a/foundry/test/protocols/UniswapV3.t.sol b/foundry/test/protocols/UniswapV3.t.sol index cbc081d..4f92dfe 100644 --- a/foundry/test/protocols/UniswapV3.t.sol +++ b/foundry/test/protocols/UniswapV3.t.sol @@ -39,7 +39,12 @@ contract UniswapV3ExecutorExposed is UniswapV3Executor { } } -contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper { +contract UniswapV3ExecutorTest is + Test, + TestUtils, + Constants, + Permit2TestHelper +{ using SafeERC20 for IERC20; UniswapV3ExecutorExposed uniswapV3Exposed; @@ -210,6 +215,10 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper { transferType ); } + + function testExportContract() public { + exportRuntimeBytecode(address(uniswapV3Exposed), "UniswapV3"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { diff --git a/foundry/test/protocols/UniswapV4.t.sol b/foundry/test/protocols/UniswapV4.t.sol index 508283f..656fd65 100644 --- a/foundry/test/protocols/UniswapV4.t.sol +++ b/foundry/test/protocols/UniswapV4.t.sol @@ -261,6 +261,10 @@ contract UniswapV4ExecutorTest is Constants, TestUtils { ); assertTrue(IERC20(WETH_ADDR).balanceOf(ALICE) == amountOut); } + + function testExportContract() public { + exportRuntimeBytecode(address(uniswapV4Exposed), "UniswapV4"); + } } contract TychoRouterForBalancerV3Test is TychoRouterTestSetup { From bbd732d15a4405fc358eedbb3cbb3b98ec3f61b5 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Thu, 11 Sep 2025 11:21:58 -0400 Subject: [PATCH 02/16] feat: bump tycho-common version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 258d4cb..e7f8184 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4634,9 +4634,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tycho-common" -version = "0.82.0" +version = "0.83.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "096c87ebe011785fcd7ed59ec501ac12b465a64fbd2914b8c0c57125c253682b" +checksum = "75ecbbf6f701a01569e351d19ee3a3e36418e8d1be539fd6ed925137eb84a2b2" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index cda8746..53c15a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] } chrono = "0.4.39" clap = { version = "4.5.3", features = ["derive"] } once_cell = "1.20.2" -tycho-common = "0.82.0" +tycho-common = "0.83.3" alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true } async-trait = { version = "0.1.88", optional = true } From 4b364299d971dfc78a019a09231fcb59f770f010 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 11 Sep 2025 15:29:22 +0000 Subject: [PATCH 03/16] chore(release): 0.124.0 [skip ci] ## [0.124.0](https://github.com/propeller-heads/tycho-execution/compare/0.123.0...0.124.0) (2025-09-11) ### Features * bump tycho-common version ([bbd732d](https://github.com/propeller-heads/tycho-execution/commit/bbd732d15a4405fc358eedbb3cbb3b98ec3f61b5)) --- CHANGELOG.md | 7 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97d7c0a..945270c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.124.0](https://github.com/propeller-heads/tycho-execution/compare/0.123.0...0.124.0) (2025-09-11) + + +### Features + +* bump tycho-common version ([bbd732d](https://github.com/propeller-heads/tycho-execution/commit/bbd732d15a4405fc358eedbb3cbb3b98ec3f61b5)) + ## [0.123.0](https://github.com/propeller-heads/tycho-execution/compare/0.122.0...0.123.0) (2025-09-02) diff --git a/Cargo.lock b/Cargo.lock index e7f8184..f849e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4659,7 +4659,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.123.0" +version = "0.124.0" dependencies = [ "alloy", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 53c15a8..78d2a01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.123.0" +version = "0.124.0" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution" From 0aa05d5621fc02e82c6664e0d5739c016f5152f7 Mon Sep 17 00:00:00 2001 From: dianacarvalho1 Date: Thu, 11 Sep 2025 17:05:51 +0100 Subject: [PATCH 04/16] Update bug report template --- .github/ISSUE_TEMPLATE/bug_report.md | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..14cf8ec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. .. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Full error traceback** +Please provide the full error traceback/failed transaction/failed tenderly simulation From 3c130e281e9f90f42e98882575a0ebb3afc880f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alan=20H=C3=B6ng?= Date: Fri, 19 Sep 2025 08:08:56 +0100 Subject: [PATCH 05/16] Update tycho-common version Updates tycho-common version so this PR builds correctly: https://github.com/propeller-heads/tycho-simulation/pull/334 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 78d2a01..d2c8a02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] } chrono = "0.4.39" clap = { version = "4.5.3", features = ["derive"] } once_cell = "1.20.2" -tycho-common = "0.83.3" +tycho-common = "0.85.0" alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true } async-trait = { version = "0.1.88", optional = true } From fa3bb6daf74c6df254a4b65718663ec0ca7339d6 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 24 Sep 2025 23:26:51 -0400 Subject: [PATCH 06/16] feat: bump tycho-common version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f849e5e..aff5879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4634,9 +4634,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tycho-common" -version = "0.83.4" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ecbbf6f701a01569e351d19ee3a3e36418e8d1be539fd6ed925137eb84a2b2" +checksum = "da3d11794b59200b15d07afdb29323b99db66e757966aa0b71af885a36bbf178" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index d2c8a02..1ccccc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] } chrono = "0.4.39" clap = { version = "4.5.3", features = ["derive"] } once_cell = "1.20.2" -tycho-common = "0.85.0" +tycho-common = "0.88.0" alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true } async-trait = { version = "0.1.88", optional = true } From 6e24223c53d116f4dbfea67201d1951af365bc9c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 25 Sep 2025 03:38:31 +0000 Subject: [PATCH 07/16] chore(release): 0.125.0 [skip ci] ## [0.125.0](https://github.com/propeller-heads/tycho-execution/compare/0.124.0...0.125.0) (2025-09-25) ### Features * bump tycho-common version ([fa3bb6d](https://github.com/propeller-heads/tycho-execution/commit/fa3bb6daf74c6df254a4b65718663ec0ca7339d6)) --- CHANGELOG.md | 7 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 945270c..3e30f11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.125.0](https://github.com/propeller-heads/tycho-execution/compare/0.124.0...0.125.0) (2025-09-25) + + +### Features + +* bump tycho-common version ([fa3bb6d](https://github.com/propeller-heads/tycho-execution/commit/fa3bb6daf74c6df254a4b65718663ec0ca7339d6)) + ## [0.124.0](https://github.com/propeller-heads/tycho-execution/compare/0.123.0...0.124.0) (2025-09-11) diff --git a/Cargo.lock b/Cargo.lock index aff5879..8a1bd2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4659,7 +4659,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.124.0" +version = "0.125.0" dependencies = [ "alloy", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 1ccccc6..8adb195 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.124.0" +version = "0.125.0" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution" From a98e8d21ccd2eafeb42805acb6ce157b60374a0c Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Mon, 22 Sep 2025 10:16:45 +0100 Subject: [PATCH 08/16] feat: Update tycho common to point to hooks feature branch Took 34 minutes Took 1 minute --- Cargo.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8adb195..a4b88fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,12 +11,12 @@ license = "MIT" categories = ["finance", "cryptography::cryptocurrencies"] readme = "README.md" exclude = [ - "foundry/*", - "foundry", - "tests/*", - "tests/common", - ".github/*", - ".gitmodules", + "foundry/*", + "foundry", + "tests/*", + "tests/common", + ".github/*", + ".gitmodules", ] [[bin]] From c51c6f52a5c1a7e47caab3bfa721f7c373a8229e Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Mon, 22 Sep 2025 12:53:11 +0100 Subject: [PATCH 09/16] feat: Add historical_trade option to encoding Adding it is necessary because sometimes we use the encoding crate for historical trades for testing. This is relevant for protocols that need token approvals like Balancer v2 and Curve. For this case, we prefer to set the approval flag to always be true than checking if it's necessary using and RPC. This RPC check would be wrong because it always uses the latest block Took 30 minutes --- src/encoding/evm/encoder_builders.rs | 12 ++++++ src/encoding/evm/encoding_utils.rs | 5 ++- .../evm/strategy_encoder/strategy_encoders.rs | 23 +++++++++++ .../evm/swap_encoder/swap_encoders.rs | 39 +++++++++++++------ src/encoding/evm/tycho_encoders.rs | 6 +++ src/encoding/models.rs | 3 ++ 6 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/encoding/evm/encoder_builders.rs b/src/encoding/evm/encoder_builders.rs index b6b6497..90f641b 100644 --- a/src/encoding/evm/encoder_builders.rs +++ b/src/encoding/evm/encoder_builders.rs @@ -23,6 +23,7 @@ pub struct TychoRouterEncoderBuilder { executors_file_path: Option, router_address: Option, swapper_pk: Option, + historical_trade: bool, } impl Default for TychoRouterEncoderBuilder { @@ -39,6 +40,7 @@ impl TychoRouterEncoderBuilder { router_address: None, swapper_pk: None, user_transfer_type: None, + historical_trade: false, } } pub fn chain(mut self, chain: Chain) -> Self { @@ -65,6 +67,15 @@ impl TychoRouterEncoderBuilder { self } + /// Sets the `historical_trade` manually to true. + /// If set to true, it means that the encoded trade will be used in an historical block (as a + /// test) and not in the current one. This is relevant for checking token approvals in some + /// protocols (like Balancer v2). + pub fn historical_trade(mut self) -> Self { + self.historical_trade = true; + self + } + /// Sets the `swapper_pk` for the encoder. This is used to sign permit2 objects. This is only /// needed if you intend to get the full calldata for the transfer. We do not recommend /// using this option, you should sign and create the function calldata entirely on your @@ -115,6 +126,7 @@ impl TychoRouterEncoderBuilder { tycho_router_address, user_transfer_type, signer, + self.historical_trade, )?)) } else { Err(EncodingError::FatalError( diff --git a/src/encoding/evm/encoding_utils.rs b/src/encoding/evm/encoding_utils.rs index 1e31f2c..5b636c2 100644 --- a/src/encoding/evm/encoding_utils.rs +++ b/src/encoding/evm/encoding_utils.rs @@ -58,11 +58,12 @@ use crate::encoding::{ /// funds. /// /// # Parameters +/// - `chain_id`: Chain ID /// - `encoded_solution`: The solution already encoded by Tycho. /// - `solution`: The high-level solution including tokens, amounts, and receiver info. -/// - `token_in_already_in_router`: Whether the input token is already present in the router. -/// - `router_address`: The address of the Tycho Router contract. +/// - `user_transfer_type`: The desired transfer method. /// - `native_address`: The address used to represent the native token +/// - `signer`: Optional signer for permit2 /// /// # Returns /// A `Result` that either contains the full transaction data (to, diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index fa47be8..e0c1255 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -26,12 +26,15 @@ use crate::encoding::{ /// * `function_signature`: String, the signature for the swap function in the router contract /// * `router_address`: Address of the router to be used to execute swaps /// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers +/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical +/// one. This is relevant for checking token approvals in some protocols (like Balancer v2). #[derive(Clone)] pub struct SingleSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, function_signature: String, router_address: Bytes, transfer_optimization: TransferOptimization, + historical_trade: bool, } impl SingleSwapStrategyEncoder { @@ -40,6 +43,7 @@ impl SingleSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, user_transfer_type: UserTransferType, router_address: Bytes, + historical_trade: bool, ) -> Result { let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 { "singleSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)" @@ -57,6 +61,7 @@ impl SingleSwapStrategyEncoder { user_transfer_type, router_address, ), + historical_trade, }) } @@ -119,6 +124,7 @@ impl StrategyEncoder for SingleSwapStrategyEncoder { group_token_in: grouped_swap.token_in.clone(), group_token_out: grouped_swap.token_out.clone(), transfer_type: transfer, + historical_trade: self.historical_trade, }; let mut grouped_protocol_data: Vec> = vec![]; @@ -171,6 +177,8 @@ impl StrategyEncoder for SingleSwapStrategyEncoder { /// * `sequential_swap_validator`: SequentialSwapValidator, responsible for checking validity of /// sequential swap solutions /// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers +/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical +/// one. This is relevant for checking token approvals in some protocols (like Balancer v2). #[derive(Clone)] pub struct SequentialSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, @@ -180,6 +188,7 @@ pub struct SequentialSwapStrategyEncoder { wrapped_address: Bytes, sequential_swap_validator: SequentialSwapValidator, transfer_optimization: TransferOptimization, + historical_trade: bool, } impl SequentialSwapStrategyEncoder { @@ -188,6 +197,7 @@ impl SequentialSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, user_transfer_type: UserTransferType, router_address: Bytes, + historical_trade: bool, ) -> Result { let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 { "sequentialSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)" @@ -210,6 +220,7 @@ impl SequentialSwapStrategyEncoder { user_transfer_type, router_address, ), + historical_trade, }) } @@ -279,6 +290,7 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder { group_token_in: grouped_swap.token_in.clone(), group_token_out: grouped_swap.token_out.clone(), transfer_type: transfer, + historical_trade: self.historical_trade, }; let mut grouped_protocol_data: Vec> = vec![]; @@ -336,6 +348,8 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder { /// solutions /// * `router_address`: Address of the router to be used to execute swaps /// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers +/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical +/// one. This is relevant for checking token approvals in some protocols (like Balancer v2). #[derive(Clone)] pub struct SplitSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, @@ -345,6 +359,7 @@ pub struct SplitSwapStrategyEncoder { split_swap_validator: SplitSwapValidator, router_address: Bytes, transfer_optimization: TransferOptimization, + historical_trade: bool, } impl SplitSwapStrategyEncoder { @@ -353,6 +368,7 @@ impl SplitSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, user_transfer_type: UserTransferType, router_address: Bytes, + historical_trade: bool, ) -> Result { let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 { "splitSwapPermit2(uint256,address,address,uint256,bool,bool,uint256,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)" @@ -374,6 +390,7 @@ impl SplitSwapStrategyEncoder { user_transfer_type, router_address, ), + historical_trade, }) } @@ -479,6 +496,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { group_token_in: grouped_swap.token_in.clone(), group_token_out: grouped_swap.token_out.clone(), transfer_type: transfer, + historical_trade: self.historical_trade, }; let mut grouped_protocol_data: Vec> = vec![]; @@ -591,6 +609,7 @@ mod tests { swap_encoder_registry, UserTransferType::TransferFromPermit2, router_address(), + false, ) .unwrap(); let solution = Solution { @@ -651,6 +670,7 @@ mod tests { swap_encoder_registry, UserTransferType::None, router_address(), + false, ) .unwrap(); let solution = Solution { @@ -732,6 +752,7 @@ mod tests { swap_encoder_registry, UserTransferType::TransferFrom, router_address(), + false, ) .unwrap(); let solution = Solution { @@ -867,6 +888,7 @@ mod tests { swap_encoder_registry, UserTransferType::TransferFromPermit2, Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"), + false, ) .unwrap(); @@ -1015,6 +1037,7 @@ mod tests { swap_encoder_registry, UserTransferType::TransferFrom, Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"), + false, ) .unwrap(); diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 134a5d6..eb8375b 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -280,19 +280,20 @@ impl SwapEncoder for BalancerV2SwapEncoder { ) -> Result, EncodingError> { let token_approvals_manager = ProtocolApprovalsManager::new()?; let token = bytes_to_address(&swap.token_in)?; - let approval_needed: bool; + let mut approval_needed: bool = true; if let Some(router_address) = &encoding_context.router_address { - let tycho_router_address = bytes_to_address(router_address)?; - approval_needed = token_approvals_manager.approval_needed( - token, - tycho_router_address, - Address::from_str(&self.vault_address) - .map_err(|_| EncodingError::FatalError("Invalid vault address".to_string()))?, - )?; - } else { - approval_needed = true; - } + if !encoding_context.historical_trade { + let tycho_router_address = bytes_to_address(router_address)?; + approval_needed = token_approvals_manager.approval_needed( + token, + tycho_router_address, + Address::from_str(&self.vault_address).map_err(|_| { + EncodingError::FatalError("Invalid vault address".to_string()) + })?, + )?; + } + }; let component_id = AlloyBytes::from_str(&swap.component.id) .map_err(|_| EncodingError::FatalError("Invalid component ID".to_string()))?; @@ -1026,6 +1027,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = UniswapV2SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -1081,6 +1083,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = UniswapV3SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -1138,6 +1141,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::None, + historical_trade: true, }; let encoder = BalancerV2SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -1207,6 +1211,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = UniswapV4SwapEncoder::new( String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"), @@ -1275,6 +1280,7 @@ mod tests { // Token out is the same as the group token out group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = UniswapV4SwapEncoder::new( @@ -1318,6 +1324,7 @@ mod tests { group_token_in: usde_address.clone(), group_token_out: wbtc_address.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; // Setup - First sequence: USDE -> USDT @@ -1448,6 +1455,7 @@ mod tests { exact_out: false, router_address: Some(Bytes::default()), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = EkuboSwapEncoder::new(String::default(), Chain::Ethereum, None).unwrap(); @@ -1490,6 +1498,7 @@ mod tests { exact_out: false, router_address: Some(Bytes::default()), transfer_type: TransferType::Transfer, + historical_trade: false, }; let first_swap = SwapBuilder::new( @@ -1687,6 +1696,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::None, + historical_trade: false, }; let encoder = CurveSwapEncoder::new( String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"), @@ -1753,6 +1763,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::None, + historical_trade: false, }; let encoder = CurveSwapEncoder::new( String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"), @@ -1820,6 +1831,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::None, + historical_trade: false, }; let encoder = CurveSwapEncoder::new( String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"), @@ -1888,6 +1900,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = BalancerV3SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -1940,6 +1953,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = MaverickV2SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -2033,6 +2047,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = BebopSwapEncoder::new( @@ -2107,6 +2122,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = HashflowSwapEncoder::new( @@ -2200,6 +2216,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), transfer_type: TransferType::Transfer, + historical_trade: false, }; let encoder = HashflowSwapEncoder::new( diff --git a/src/encoding/evm/tycho_encoders.rs b/src/encoding/evm/tycho_encoders.rs index 2710d71..79632db 100644 --- a/src/encoding/evm/tycho_encoders.rs +++ b/src/encoding/evm/tycho_encoders.rs @@ -54,6 +54,7 @@ impl TychoRouterEncoder { router_address: Bytes, user_transfer_type: UserTransferType, signer: Option, + historical_trade: bool, ) -> Result { let permit2 = if user_transfer_type == UserTransferType::TransferFromPermit2 { Some(Permit2::new()?) @@ -66,18 +67,21 @@ impl TychoRouterEncoder { swap_encoder_registry.clone(), user_transfer_type.clone(), router_address.clone(), + historical_trade.clone(), )?, sequential_swap_strategy: SequentialSwapStrategyEncoder::new( chain, swap_encoder_registry.clone(), user_transfer_type.clone(), router_address.clone(), + historical_trade.clone(), )?, split_swap_strategy: SplitSwapStrategyEncoder::new( chain, swap_encoder_registry, user_transfer_type.clone(), router_address.clone(), + historical_trade, )?, router_address, permit2, @@ -331,6 +335,7 @@ impl TychoExecutorEncoder { group_token_in: grouped_swap.token_in.clone(), group_token_out: grouped_swap.token_out.clone(), transfer_type: transfer, + historical_trade: false, }; let mut grouped_protocol_data: Vec> = vec![]; let mut initial_protocol_data: Vec = vec![]; @@ -498,6 +503,7 @@ mod tests { router_address(), user_transfer_type, None, + false, ) .unwrap() } diff --git a/src/encoding/models.rs b/src/encoding/models.rs index 48b224c..b7886ba 100644 --- a/src/encoding/models.rs +++ b/src/encoding/models.rs @@ -273,6 +273,8 @@ impl PartialEq for PermitDetails { /// * `group_token_in`: Token to be used as the input for the group swap. /// * `group_token_out`: Token to be used as the output for the group swap. /// * `transfer`: Type of transfer to be performed. See `TransferType` for more details. +/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical +/// one. This is relevant for checking token approvals in some protocols (like Balancer v2). #[derive(Clone, Debug)] pub struct EncodingContext { pub receiver: Bytes, @@ -281,6 +283,7 @@ pub struct EncodingContext { pub group_token_in: Bytes, pub group_token_out: Bytes, pub transfer_type: TransferType, + pub historical_trade: bool, } /// Represents the type of transfer to be performed into the pool. From e78a362894955a8b0e676bbcb189195d00815aad Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 23 Sep 2025 09:32:46 +0100 Subject: [PATCH 10/16] feat: Pass the file contents instead of the file path for executors This is better because passing paths around might be really complex when running the code in another environments that is not local Took 30 minutes --- src/bin/tycho-encode.rs | 13 ++++++++-- src/encoding/evm/encoder_builders.rs | 26 +++++++++---------- .../evm/strategy_encoder/strategy_encoders.rs | 7 ++--- .../evm/swap_encoder/swap_encoder_registry.rs | 12 +++------ src/encoding/evm/tycho_encoders.rs | 14 +++++----- tests/common/mod.rs | 5 ++-- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/bin/tycho-encode.rs b/src/bin/tycho-encode.rs index 161f7ae..d0252dc 100644 --- a/src/bin/tycho-encode.rs +++ b/src/bin/tycho-encode.rs @@ -1,9 +1,13 @@ -use std::io::{self, Read}; +use std::{ + fs, + io::{self, Read}, +}; use alloy::sol_types::SolValue; use clap::{Parser, Subcommand}; use tycho_common::{hex_bytes::Bytes, models::Chain}; use tycho_execution::encoding::{ + errors::EncodingError, evm::{ approvals::permit2::PermitSingle, encoder_builders::{TychoExecutorEncoderBuilder, TychoRouterEncoderBuilder}, @@ -83,7 +87,12 @@ fn main() -> Result<(), Box> { Commands::TychoRouter => { let mut builder = TychoRouterEncoderBuilder::new().chain(chain); if let Some(config_path) = cli.executors_file_path { - builder = builder.executors_file_path(config_path); + let executors_addresses = fs::read_to_string(&config_path).map_err(|e| { + EncodingError::FatalError(format!( + "Error reading executors file from {config_path:?}: {e}", + )) + })?; + builder = builder.executors_addresses(executors_addresses); } if let Some(router_address) = cli.router_address { builder = builder.router_address(router_address); diff --git a/src/encoding/evm/encoder_builders.rs b/src/encoding/evm/encoder_builders.rs index 90f641b..703f083 100644 --- a/src/encoding/evm/encoder_builders.rs +++ b/src/encoding/evm/encoder_builders.rs @@ -20,7 +20,7 @@ use crate::encoding::{ pub struct TychoRouterEncoderBuilder { chain: Option, user_transfer_type: Option, - executors_file_path: Option, + executors_addresses: Option, router_address: Option, swapper_pk: Option, historical_trade: bool, @@ -36,7 +36,7 @@ impl TychoRouterEncoderBuilder { pub fn new() -> Self { TychoRouterEncoderBuilder { chain: None, - executors_file_path: None, + executors_addresses: None, router_address: None, swapper_pk: None, user_transfer_type: None, @@ -53,10 +53,10 @@ impl TychoRouterEncoderBuilder { self } - /// Sets the `executors_file_path` manually. - /// If it's not set, the default path will be used (config/executor_addresses.json) - pub fn executors_file_path(mut self, executors_file_path: String) -> Self { - self.executors_file_path = Some(executors_file_path); + /// Sets the `executors_addresses` manually. + /// If it's not set, the default value will be used (contents of config/executor_addresses.json) + pub fn executors_addresses(mut self, executors_addresses: String) -> Self { + self.executors_addresses = Some(executors_addresses); self } @@ -107,7 +107,7 @@ impl TychoRouterEncoderBuilder { } let swap_encoder_registry = - SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?; + SwapEncoderRegistry::new(self.executors_addresses.clone(), chain)?; let signer = if let Some(pk) = self.swapper_pk { let pk = B256::from_str(&pk).map_err(|_| { @@ -140,7 +140,7 @@ impl TychoRouterEncoderBuilder { /// Builder pattern for constructing a `TychoExecutorEncoder` with customizable options. pub struct TychoExecutorEncoderBuilder { chain: Option, - executors_file_path: Option, + executors_addresses: Option, } impl Default for TychoExecutorEncoderBuilder { @@ -151,17 +151,17 @@ impl Default for TychoExecutorEncoderBuilder { impl TychoExecutorEncoderBuilder { pub fn new() -> Self { - TychoExecutorEncoderBuilder { chain: None, executors_file_path: None } + TychoExecutorEncoderBuilder { chain: None, executors_addresses: None } } pub fn chain(mut self, chain: Chain) -> Self { self.chain = Some(chain); self } - /// Sets the `executors_file_path` manually. + /// Sets the `executors_addresses` manually. /// If it's not set, the default path will be used (config/executor_addresses.json) - pub fn executors_file_path(mut self, executors_file_path: String) -> Self { - self.executors_file_path = Some(executors_file_path); + pub fn executors_addresses(mut self, executors_addresses: String) -> Self { + self.executors_addresses = Some(executors_addresses); self } @@ -170,7 +170,7 @@ impl TychoExecutorEncoderBuilder { pub fn build(self) -> Result, EncodingError> { if let Some(chain) = self.chain { let swap_encoder_registry = - SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?; + SwapEncoderRegistry::new(self.executors_addresses.clone(), chain)?; Ok(Box::new(TychoExecutorEncoder::new(swap_encoder_registry)?)) } else { Err(EncodingError::FatalError( diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index e0c1255..44f5503 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -553,7 +553,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { #[cfg(test)] mod tests { - use std::{collections::HashMap, str::FromStr}; + use std::{collections::HashMap, fs, str::FromStr}; use alloy::{hex::encode, primitives::hex}; use num_bigint::{BigInt, BigUint}; @@ -573,9 +573,10 @@ mod tests { } fn get_swap_encoder_registry() -> SwapEncoderRegistry { + let executors_addresses = + fs::read_to_string("config/test_executor_addresses.json").unwrap(); let eth_chain = eth_chain(); - SwapEncoderRegistry::new(Some("config/test_executor_addresses.json".to_string()), eth_chain) - .unwrap() + SwapEncoderRegistry::new(Some(executors_addresses), eth_chain).unwrap() } fn router_address() -> Bytes { diff --git a/src/encoding/evm/swap_encoder/swap_encoder_registry.rs b/src/encoding/evm/swap_encoder/swap_encoder_registry.rs index 221ea76..a9955a3 100644 --- a/src/encoding/evm/swap_encoder/swap_encoder_registry.rs +++ b/src/encoding/evm/swap_encoder/swap_encoder_registry.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fs}; +use std::collections::HashMap; use tycho_common::models::Chain; @@ -21,13 +21,9 @@ pub struct SwapEncoderRegistry { impl SwapEncoderRegistry { /// Populates the registry with the `SwapEncoders` for the given blockchain by parsing the /// executors' addresses in the file at the given path. - pub fn new(executors_file_path: Option, chain: Chain) -> Result { - let config_str = if let Some(ref path) = executors_file_path { - fs::read_to_string(path).map_err(|e| { - EncodingError::FatalError(format!( - "Error reading executors file from {executors_file_path:?}: {e}", - )) - })? + pub fn new(executors_addresses: Option, chain: Chain) -> Result { + let config_str = if let Some(addresses) = executors_addresses { + addresses } else { DEFAULT_EXECUTORS_JSON.to_string() }; diff --git a/src/encoding/evm/tycho_encoders.rs b/src/encoding/evm/tycho_encoders.rs index 79632db..e6cae0d 100644 --- a/src/encoding/evm/tycho_encoders.rs +++ b/src/encoding/evm/tycho_encoders.rs @@ -67,14 +67,14 @@ impl TychoRouterEncoder { swap_encoder_registry.clone(), user_transfer_type.clone(), router_address.clone(), - historical_trade.clone(), + historical_trade, )?, sequential_swap_strategy: SequentialSwapStrategyEncoder::new( chain, swap_encoder_registry.clone(), user_transfer_type.clone(), router_address.clone(), - historical_trade.clone(), + historical_trade, )?, split_swap_strategy: SplitSwapStrategyEncoder::new( chain, @@ -405,7 +405,7 @@ impl TychoEncoder for TychoExecutorEncoder { #[cfg(test)] mod tests { - use std::{collections::HashMap, str::FromStr}; + use std::{collections::HashMap, fs, str::FromStr}; use num_bigint::{BigInt, BigUint}; use tycho_common::models::{protocol::ProtocolComponent, Chain}; @@ -489,11 +489,9 @@ mod tests { } fn get_swap_encoder_registry() -> SwapEncoderRegistry { - SwapEncoderRegistry::new( - Some("config/test_executor_addresses.json".to_string()), - eth_chain(), - ) - .unwrap() + let executors_addresses = + fs::read_to_string("config/test_executor_addresses.json").unwrap(); + SwapEncoderRegistry::new(Some(executors_addresses), eth_chain()).unwrap() } fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> TychoRouterEncoder { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 0949b7e..a6be289 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] pub mod encoding; -use std::str::FromStr; +use std::{fs, str::FromStr}; use alloy::{ primitives::{B256, U256}, @@ -71,10 +71,11 @@ pub fn get_signer() -> PrivateKeySigner { } pub fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> Box { + let executors_addresses = fs::read_to_string("config/test_executor_addresses.json").unwrap(); TychoRouterEncoderBuilder::new() .chain(Chain::Ethereum) .user_transfer_type(user_transfer_type) - .executors_file_path("config/test_executor_addresses.json".to_string()) + .executors_addresses(executors_addresses) .router_address(router_address()) .build() .expect("Failed to build encoder") From 1bc5604bdfd4fc2f1f21f45ba0d48ea62610d9d5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 25 Sep 2025 08:40:09 +0000 Subject: [PATCH 11/16] chore(release): 0.126.0 [skip ci] ## [0.126.0](https://github.com/propeller-heads/tycho-execution/compare/0.125.0...0.126.0) (2025-09-25) ### Features * Add historical_trade option to encoding ([c51c6f5](https://github.com/propeller-heads/tycho-execution/commit/c51c6f52a5c1a7e47caab3bfa721f7c373a8229e)) * Pass the file contents instead of the file path for executors ([e78a362](https://github.com/propeller-heads/tycho-execution/commit/e78a362894955a8b0e676bbcb189195d00815aad)) * Update tycho common to point to hooks feature branch ([a98e8d2](https://github.com/propeller-heads/tycho-execution/commit/a98e8d21ccd2eafeb42805acb6ce157b60374a0c)) --- 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 3e30f11..a3f7886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [0.126.0](https://github.com/propeller-heads/tycho-execution/compare/0.125.0...0.126.0) (2025-09-25) + + +### Features + +* Add historical_trade option to encoding ([c51c6f5](https://github.com/propeller-heads/tycho-execution/commit/c51c6f52a5c1a7e47caab3bfa721f7c373a8229e)) +* Pass the file contents instead of the file path for executors ([e78a362](https://github.com/propeller-heads/tycho-execution/commit/e78a362894955a8b0e676bbcb189195d00815aad)) +* Update tycho common to point to hooks feature branch ([a98e8d2](https://github.com/propeller-heads/tycho-execution/commit/a98e8d21ccd2eafeb42805acb6ce157b60374a0c)) + ## [0.125.0](https://github.com/propeller-heads/tycho-execution/compare/0.124.0...0.125.0) (2025-09-25) diff --git a/Cargo.lock b/Cargo.lock index 8a1bd2b..b407e60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4659,7 +4659,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.125.0" +version = "0.126.0" dependencies = [ "alloy", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index a4b88fd..4c181e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.125.0" +version = "0.126.0" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution" From 5d73e3b47c5cbff4fa0c88e71f15f48f3831f199 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Thu, 25 Sep 2025 10:48:04 +0100 Subject: [PATCH 12/16] feat: Use tycho-common from github Took 20 seconds --- Cargo.lock | 3 +-- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a1bd2b..17bf57c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4635,8 +4635,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tycho-common" version = "0.88.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3d11794b59200b15d07afdb29323b99db66e757966aa0b71af885a36bbf178" +source = "git+https://github.com/propeller-heads/tycho-indexer.git?tag=0.88.0#47ed2e3db5e6b038866c682964ca0112c27d9ae1" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index a4b88fd..1a27f56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] } chrono = "0.4.39" clap = { version = "4.5.3", features = ["derive"] } once_cell = "1.20.2" -tycho-common = "0.88.0" +tycho-common = { git = "https://github.com/propeller-heads/tycho-indexer.git", package = "tycho-common", tag = "0.88.0" } alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true } async-trait = { version = "0.1.88", optional = true } From ae5c3778eae88a9c14878dc5cc6853df62b4ceac Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 25 Sep 2025 10:15:52 +0000 Subject: [PATCH 13/16] chore(release): 0.127.0 [skip ci] ## [0.127.0](https://github.com/propeller-heads/tycho-execution/compare/0.126.0...0.127.0) (2025-09-25) ### Features * Use tycho-common from github ([5d73e3b](https://github.com/propeller-heads/tycho-execution/commit/5d73e3b47c5cbff4fa0c88e71f15f48f3831f199)) --- CHANGELOG.md | 7 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3f7886..02ca7fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.127.0](https://github.com/propeller-heads/tycho-execution/compare/0.126.0...0.127.0) (2025-09-25) + + +### Features + +* Use tycho-common from github ([5d73e3b](https://github.com/propeller-heads/tycho-execution/commit/5d73e3b47c5cbff4fa0c88e71f15f48f3831f199)) + ## [0.126.0](https://github.com/propeller-heads/tycho-execution/compare/0.125.0...0.126.0) (2025-09-25) diff --git a/Cargo.lock b/Cargo.lock index 69a7d10..25d5bd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4658,7 +4658,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.126.0" +version = "0.127.0" dependencies = [ "alloy", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index fdbc847..b9ed8c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.126.0" +version = "0.127.0" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution" From 89435b5c76bbd1fbf2c946686ede442c4647cd29 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Thu, 25 Sep 2025 11:38:55 +0100 Subject: [PATCH 14/16] feat: Use tycho-common from crates.io This fixes previously borked version Took 1 minute --- Cargo.lock | 5 +++-- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25d5bd8..cfe3192 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4634,8 +4634,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tycho-common" -version = "0.88.0" -source = "git+https://github.com/propeller-heads/tycho-indexer.git?tag=0.88.0#47ed2e3db5e6b038866c682964ca0112c27d9ae1" +version = "0.88.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0c309443e15797f3b713f10b8f00e79067abe91ea7c58421e4ce345b022e0d" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index b9ed8c8..d4f0211 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] } chrono = "0.4.39" clap = { version = "4.5.3", features = ["derive"] } once_cell = "1.20.2" -tycho-common = { git = "https://github.com/propeller-heads/tycho-indexer.git", package = "tycho-common", tag = "0.88.0" } +tycho-common = "0.88.0" alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true } async-trait = { version = "0.1.88", optional = true } From 17780db05c5894d69fbc0e4bd524a7339f703fd0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 25 Sep 2025 11:03:28 +0000 Subject: [PATCH 15/16] chore(release): 0.128.0 [skip ci] ## [0.128.0](https://github.com/propeller-heads/tycho-execution/compare/0.127.0...0.128.0) (2025-09-25) ### Features * Use tycho-common from crates.io ([89435b5](https://github.com/propeller-heads/tycho-execution/commit/89435b5c76bbd1fbf2c946686ede442c4647cd29)) --- CHANGELOG.md | 7 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ca7fc..e109013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.128.0](https://github.com/propeller-heads/tycho-execution/compare/0.127.0...0.128.0) (2025-09-25) + + +### Features + +* Use tycho-common from crates.io ([89435b5](https://github.com/propeller-heads/tycho-execution/commit/89435b5c76bbd1fbf2c946686ede442c4647cd29)) + ## [0.127.0](https://github.com/propeller-heads/tycho-execution/compare/0.126.0...0.127.0) (2025-09-25) diff --git a/Cargo.lock b/Cargo.lock index cfe3192..eca6a6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4659,7 +4659,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.127.0" +version = "0.128.0" dependencies = [ "alloy", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index d4f0211..c5455ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.127.0" +version = "0.128.0" edition = "2021" description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors." repository = "https://github.com/propeller-heads/tycho-execution" From 17e115c77b9ca628f3da30d15ba3d35592503281 Mon Sep 17 00:00:00 2001 From: johnwhitton Date: Thu, 17 Jul 2025 16:04:02 -0700 Subject: [PATCH 16/16] Update v4-core and v4-periphery to latest version --- foundry/.env.example | 2 ++ foundry/lib/v4-core | 2 +- foundry/lib/v4-periphery | 2 +- foundry/src/executors/UniswapV4Executor.sol | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 foundry/.env.example diff --git a/foundry/.env.example b/foundry/.env.example new file mode 100644 index 0000000..224e3f1 --- /dev/null +++ b/foundry/.env.example @@ -0,0 +1,2 @@ +# Local Anvil Testing Private Key and Address +RPC_URL=https://eth-mainnet.g.alchemy.com/v2/ \ No newline at end of file diff --git a/foundry/lib/v4-core b/foundry/lib/v4-core index e50237c..59d3ecf 160000 --- a/foundry/lib/v4-core +++ b/foundry/lib/v4-core @@ -1 +1 @@ -Subproject commit e50237c43811bd9b526eff40f26772152a42daba +Subproject commit 59d3ecf53afa9264a16bba0e38f4c5d2231f80bc diff --git a/foundry/lib/v4-periphery b/foundry/lib/v4-periphery index cf451c4..ad04c9f 160000 --- a/foundry/lib/v4-periphery +++ b/foundry/lib/v4-periphery @@ -1 +1 @@ -Subproject commit cf451c4f55f36ea64c2007d331e3a3574225fc8b +Subproject commit ad04c9f24a170accf5ea1b2836bbafd514537ca6 diff --git a/foundry/src/executors/UniswapV4Executor.sol b/foundry/src/executors/UniswapV4Executor.sol index eceb410..8f245f6 100644 --- a/foundry/src/executors/UniswapV4Executor.sol +++ b/foundry/src/executors/UniswapV4Executor.sol @@ -9,6 +9,7 @@ import { } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol"; import { Currency, CurrencyLibrary } from "@uniswap/v4-core/src/types/Currency.sol"; @@ -354,7 +355,7 @@ contract UniswapV4Executor is // slither-disable-next-line calls-loop BalanceDelta delta = poolManager.swap( poolKey, - IPoolManager.SwapParams( + SwapParams( zeroForOne, amountSpecified, zeroForOne