From 0ac722d91f6c2f7c09531f5f56f057d1fe014c6f Mon Sep 17 00:00:00 2001 From: zach Date: Wed, 19 Mar 2025 09:23:43 +0800 Subject: [PATCH 01/19] feat: add mav executor --- foundry/src/executors/MaverickV2Executor.sol | 93 +++++++++++++++++++ foundry/test/Constants.sol | 6 ++ .../test/executors/MaverickV2Executor.t.sol | 77 +++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 foundry/src/executors/MaverickV2Executor.sol create mode 100644 foundry/test/executors/MaverickV2Executor.t.sol diff --git a/foundry/src/executors/MaverickV2Executor.sol b/foundry/src/executors/MaverickV2Executor.sol new file mode 100644 index 0000000..a5971c2 --- /dev/null +++ b/foundry/src/executors/MaverickV2Executor.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.26; + +import "@interfaces/IExecutor.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +error MaverickV2Executor__InvalidDataLength(); +error MaverickV2Executor__InvalidTarget(); +error MaverickV2Executor__InvalidFactory(); + +contract MaverickV2Executor is IExecutor { + using SafeERC20 for IERC20; + + address public immutable factory; + address private immutable self; + + constructor(address _factory) { + if (_factory == address(0)) { + revert MaverickV2Executor__InvalidFactory(); + } + factory = _factory; + self = address(this); + } + + // slither-disable-next-line locked-ether + function swap(uint256 givenAmount, bytes calldata data) + external + payable + returns (uint256 calculatedAmount) + { + address target; + address receiver; + IERC20 tokenIn; + + (tokenIn, target, receiver) = _decodeData(data); + + _verifyPairAddress(target); + IMaverickV2Pool pool = IMaverickV2Pool(target); + + bool isTokenAIn = pool.tokenA() == tokenIn; + int32 tickLimit = isTokenAIn ? type(int32).max : type(int32).min; + IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool + .SwapParams({ + amount: givenAmount, + tokenAIn: isTokenAIn, + exactOutput: false, + tickLimit: tickLimit + }); + IERC20(tokenIn).safeTransfer(target, givenAmount); + (, calculatedAmount) = pool.swap(receiver, swapParams, ""); + } + + function _decodeData(bytes calldata data) + internal + pure + returns (IERC20 inToken, address target, address receiver) + { + if (data.length != 60) { + revert MaverickV2Executor__InvalidDataLength(); + } + inToken = IERC20(address(bytes20(data[0:20]))); + target = address(bytes20(data[20:40])); + receiver = address(bytes20(data[40:60])); + } + + function _verifyPairAddress(address target) internal view { + if (!IMaverickV2Factory(factory).isFactoryPool(IMaverickV2Pool(target))) { + revert MaverickV2Executor__InvalidTarget(); + } + } +} + +interface IMaverickV2Factory { + function isFactoryPool(IMaverickV2Pool pool) external view returns (bool); +} + +interface IMaverickV2Pool { + struct SwapParams { + uint256 amount; + bool tokenAIn; + bool exactOutput; + int32 tickLimit; + } + + function swap( + address recipient, + SwapParams memory params, + bytes calldata data + ) external returns (uint256 amountIn, uint256 amountOut); + + function tokenA() external view returns (IERC20); + function tokenB() external view returns (IERC20); +} diff --git a/foundry/test/Constants.sol b/foundry/test/Constants.sol index 9b0f488..51b292d 100644 --- a/foundry/test/Constants.sol +++ b/foundry/test/Constants.sol @@ -56,6 +56,12 @@ contract Constants is Test, BaseConstants { address WSTTAO_ADDR = address(0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67); address WTAO_ADDR = address(0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44); address BSGG_ADDR = address(0xdA16Cf041E2780618c49Dbae5d734B89a6Bac9b3); + address GHO_ADDR = address(0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f); + + // Maverick v2 + address MAVERICK_V2_FACTORY = 0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e; + address GHO_USDC_POOL = 0x14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67; + // Uniswap v2 address WETH_DAI_POOL = 0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11; address DAI_USDC_POOL = 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5; diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol new file mode 100644 index 0000000..8d7fe6b --- /dev/null +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.26; + +import "@src/executors/MaverickV2Executor.sol"; +import {Test} from "../../lib/forge-std/src/Test.sol"; +import {Constants} from "../Constants.sol"; + +contract MaverickV2ExecutorExposed is MaverickV2Executor { + constructor(address _factory) MaverickV2Executor(_factory) {} + function decodeParams(bytes calldata data) + external + pure + returns ( + IERC20 tokenIn, + address target, + address receiver + ) + { + return _decodeData(data); + } +} + +contract MaverickV2ExecutorTest is + Test, + Constants +{ + using SafeERC20 for IERC20; + + MaverickV2ExecutorExposed maverickV2Exposed; + IERC20 GHO = IERC20(GHO_ADDR); + IERC20 USDC = IERC20(USDC_ADDR); + + function setUp() public { + uint256 forkBlock = 20127232; + vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); + maverickV2Exposed = new MaverickV2ExecutorExposed(MAVERICK_V2_FACTORY); + } + + function testDecodeParams() public view { + bytes memory params = abi.encodePacked( + GHO_ADDR, GHO_USDC_POOL, address(2) + ); + + ( + IERC20 tokenIn, + address target, + address receiver + ) = maverickV2Exposed.decodeParams(params); + + assertEq(address(tokenIn), GHO_ADDR); + assertEq(target, GHO_USDC_POOL); + assertEq(receiver, address(2)); + } + + function testDecodeParamsInvalidDataLength() public { + bytes memory invalidParams = + abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2), true); + + vm.expectRevert(MaverickV2Executor__InvalidDataLength.selector); + maverickV2Exposed.decodeParams(invalidParams); + } + + function testSwap() public { + uint256 amountIn = 10 ** 18; + bytes memory protocolData = + abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2)); + + deal(GHO_ADDR, address(maverickV2Exposed), amountIn); + uint256 balanceBefore = GHO.balanceOf(BOB); + + uint256 amountOut = maverickV2Exposed.swap(amountIn, protocolData); + + uint256 balanceAfter = GHO.balanceOf(BOB); + assertGt(balanceAfter, balanceBefore); + assertEq(balanceAfter - balanceBefore, amountOut); + } +} From 72a651d453943d554722d0fa4818255fbec01ce5 Mon Sep 17 00:00:00 2001 From: zach Date: Thu, 20 Mar 2025 09:17:48 +0800 Subject: [PATCH 02/19] feat: add swap encode --- foundry/src/executors/MaverickV2Executor.sol | 3 +- .../test/executors/MaverickV2Executor.t.sol | 53 ++++++++---- .../evm/swap_encoder/swap_encoders.rs | 82 +++++++++++++++++++ 3 files changed, 120 insertions(+), 18 deletions(-) diff --git a/foundry/src/executors/MaverickV2Executor.sol b/foundry/src/executors/MaverickV2Executor.sol index a5971c2..08c0350 100644 --- a/foundry/src/executors/MaverickV2Executor.sol +++ b/foundry/src/executors/MaverickV2Executor.sol @@ -64,7 +64,8 @@ contract MaverickV2Executor is IExecutor { } function _verifyPairAddress(address target) internal view { - if (!IMaverickV2Factory(factory).isFactoryPool(IMaverickV2Pool(target))) { + if (!IMaverickV2Factory(factory).isFactoryPool(IMaverickV2Pool(target))) + { revert MaverickV2Executor__InvalidTarget(); } } diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol index 8d7fe6b..14769e9 100644 --- a/foundry/test/executors/MaverickV2Executor.t.sol +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -7,23 +7,17 @@ import {Constants} from "../Constants.sol"; contract MaverickV2ExecutorExposed is MaverickV2Executor { constructor(address _factory) MaverickV2Executor(_factory) {} + function decodeParams(bytes calldata data) external pure - returns ( - IERC20 tokenIn, - address target, - address receiver - ) + returns (IERC20 tokenIn, address target, address receiver) { return _decodeData(data); } } -contract MaverickV2ExecutorTest is - Test, - Constants -{ +contract MaverickV2ExecutorTest is Test, Constants { using SafeERC20 for IERC20; MaverickV2ExecutorExposed maverickV2Exposed; @@ -37,15 +31,11 @@ contract MaverickV2ExecutorTest is } function testDecodeParams() public view { - bytes memory params = abi.encodePacked( - GHO_ADDR, GHO_USDC_POOL, address(2) - ); + bytes memory params = + abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2)); - ( - IERC20 tokenIn, - address target, - address receiver - ) = maverickV2Exposed.decodeParams(params); + (IERC20 tokenIn, address target, address receiver) = + maverickV2Exposed.decodeParams(params); assertEq(address(tokenIn), GHO_ADDR); assertEq(target, GHO_USDC_POOL); @@ -74,4 +64,33 @@ contract MaverickV2ExecutorTest is assertGt(balanceAfter, balanceBefore); assertEq(balanceAfter - balanceBefore, amountOut); } + + function testDecodeIntegration() public view { + // Generated by the SwapEncoder - test_encode_maverick_v2 + bytes memory protocolData = + hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"; + + (IERC20 tokenIn, address pool, address receiver) = + maverickV2Exposed.decodeParams(protocolData); + + assertEq(address(tokenIn), GHO_ADDR); + assertEq(pool, GHO_USDC_POOL); + assertEq(receiver, BOB); + } + + function testSwapIntegration() public { + // Generated by the SwapEncoder - test_encode_maverick_v2 + bytes memory protocolData = + hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"; + + uint256 amountIn = 10 ** 18; + deal(GHO_ADDR, address(maverickV2Exposed), amountIn); + uint256 balanceBefore = GHO.balanceOf(BOB); + + uint256 amountOut = maverickV2Exposed.swap(amountIn, protocolData); + + uint256 balanceAfter = USDC.balanceOf(BOB); + assertGt(balanceAfter, balanceBefore); + assertEq(balanceAfter - balanceBefore, amountOut); + } } diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index cf41e88..7f9c8c4 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -560,6 +560,45 @@ impl SwapEncoder for CurveSwapEncoder { } } +/// Encodes a swap on a Maverick V2 pool through the given executor address. +/// +/// # Fields +/// * `executor_address` - The address of the executor contract that will perform the swap. +#[derive(Clone)] +pub struct MaverickV2SwapEncoder { + executor_address: String, +} + +impl SwapEncoder for MaverickV2SwapEncoder { + fn new(executor_address: String) -> Self { + Self { + executor_address, + } + } + fn encode_swap( + &self, + swap: Swap, + encoding_context: EncodingContext, + ) -> Result, EncodingError> { + let component_id = AlloyBytes::from_str(&swap.component.id) + .map_err(|_| EncodingError::FatalError("Invalid component ID".to_string()))?; + + let args = ( + bytes_to_address(&swap.token_in)?, + component_id, + bytes_to_address(&encoding_context.receiver)?, + ); + Ok(args.abi_encode_packed()) + } + + fn executor_address(&self) -> &str { + &self.executor_address + } + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} + #[cfg(test)] mod tests { use std::collections::HashMap; @@ -1394,4 +1433,47 @@ mod tests { ); } } + + #[test] + fn test_encode_maverick_v2() { + let maverick_pool = ProtocolComponent { + id: String::from("0x14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67"), + protocol_system: String::from("vm:maverick_v2"), + ..Default::default() + }; + let token_in = Bytes::from("0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f"); + let token_out = Bytes::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + let swap = Swap { + component: maverick_pool, + token_in: token_in.clone(), + token_out: token_out.clone(), + split: 0f64, + }; + let encoding_context = EncodingContext { + // The receiver was generated with `makeAddr("bob") using forge` + receiver: Bytes::from("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"), + exact_out: false, + router_address: Bytes::zero(20), + group_token_in: token_in.clone(), + group_token_out: token_out.clone(), + }; + let encoder = + MaverickV2SwapEncoder::new(String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4")); + let encoded_swap = encoder + .encode_swap(swap, encoding_context) + .unwrap(); + let hex_swap = encode(&encoded_swap); + + assert_eq!( + hex_swap, + String::from(concat!( + // token in + "40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f", + // pool + "14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67", + // receiver + "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e", + )).to_lowercase() + ); + } } From d103ca9e33f931f18c8af79efa5d77d801bab2e9 Mon Sep 17 00:00:00 2001 From: zach Date: Wed, 26 Mar 2025 23:04:45 +0800 Subject: [PATCH 03/19] fix: swap test --- foundry/test/executors/MaverickV2Executor.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol index 14769e9..09b6793 100644 --- a/foundry/test/executors/MaverickV2Executor.t.sol +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -53,7 +53,7 @@ contract MaverickV2ExecutorTest is Test, Constants { function testSwap() public { uint256 amountIn = 10 ** 18; bytes memory protocolData = - abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2)); + abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, BOB); deal(GHO_ADDR, address(maverickV2Exposed), amountIn); uint256 balanceBefore = GHO.balanceOf(BOB); From 4c938306bda62d37b8932697f98d0d667a96532b Mon Sep 17 00:00:00 2001 From: zach Date: Thu, 27 Mar 2025 06:27:07 +0800 Subject: [PATCH 04/19] fix: maverick test fork block --- foundry/test/executors/MaverickV2Executor.t.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol index 09b6793..dcba37c 100644 --- a/foundry/test/executors/MaverickV2Executor.t.sol +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -25,7 +25,7 @@ contract MaverickV2ExecutorTest is Test, Constants { IERC20 USDC = IERC20(USDC_ADDR); function setUp() public { - uint256 forkBlock = 20127232; + uint256 forkBlock = 22096000; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); maverickV2Exposed = new MaverickV2ExecutorExposed(MAVERICK_V2_FACTORY); } @@ -51,16 +51,16 @@ contract MaverickV2ExecutorTest is Test, Constants { } function testSwap() public { - uint256 amountIn = 10 ** 18; + uint256 amountIn = 10e18; bytes memory protocolData = abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, BOB); deal(GHO_ADDR, address(maverickV2Exposed), amountIn); - uint256 balanceBefore = GHO.balanceOf(BOB); + uint256 balanceBefore = USDC.balanceOf(BOB); uint256 amountOut = maverickV2Exposed.swap(amountIn, protocolData); - uint256 balanceAfter = GHO.balanceOf(BOB); + uint256 balanceAfter = USDC.balanceOf(BOB); assertGt(balanceAfter, balanceBefore); assertEq(balanceAfter - balanceBefore, amountOut); } @@ -85,7 +85,7 @@ contract MaverickV2ExecutorTest is Test, Constants { uint256 amountIn = 10 ** 18; deal(GHO_ADDR, address(maverickV2Exposed), amountIn); - uint256 balanceBefore = GHO.balanceOf(BOB); + uint256 balanceBefore = USDC.balanceOf(BOB); uint256 amountOut = maverickV2Exposed.swap(amountIn, protocolData); From bd642d7b453e1b860c1b5909022e41de1c70b5bd Mon Sep 17 00:00:00 2001 From: zach Date: Thu, 3 Apr 2025 09:30:34 +0800 Subject: [PATCH 05/19] update --- src/encoding/evm/swap_encoder/swap_encoders.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 7f9c8c4..370f638 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -571,9 +571,7 @@ pub struct MaverickV2SwapEncoder { impl SwapEncoder for MaverickV2SwapEncoder { fn new(executor_address: String) -> Self { - Self { - executor_address, - } + Self { executor_address } } fn encode_swap( &self, @@ -1473,7 +1471,8 @@ mod tests { "14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67", // receiver "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e", - )).to_lowercase() + )) + .to_lowercase() ); } } From bab30e3958ee62091b322ac0bc540939c050ee9e Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 11 Apr 2025 08:43:03 +0800 Subject: [PATCH 06/19] fix: add maverick for build --- src/encoding/evm/swap_encoder/builder.rs | 9 +++++++-- .../evm/swap_encoder/swap_encoders.rs | 20 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/encoding/evm/swap_encoder/builder.rs b/src/encoding/evm/swap_encoder/builder.rs index bbe2c2d..735029c 100644 --- a/src/encoding/evm/swap_encoder/builder.rs +++ b/src/encoding/evm/swap_encoder/builder.rs @@ -3,8 +3,8 @@ use std::collections::HashMap; use crate::encoding::{ errors::EncodingError, evm::swap_encoder::swap_encoders::{ - BalancerV2SwapEncoder, CurveSwapEncoder, EkuboSwapEncoder, UniswapV2SwapEncoder, - UniswapV3SwapEncoder, UniswapV4SwapEncoder, + BalancerV2SwapEncoder, CurveSwapEncoder, EkuboSwapEncoder, MaverickV2SwapEncoder, + UniswapV2SwapEncoder, UniswapV3SwapEncoder, UniswapV4SwapEncoder, }, models::Chain, swap_encoder::SwapEncoder, @@ -76,6 +76,11 @@ impl SwapEncoderBuilder { "vm:curve" => { Ok(Box::new(CurveSwapEncoder::new(self.executor_address, self.chain, self.config)?)) } + "vm::maverick_v2" => Ok(Box::new(MaverickV2SwapEncoder::new( + self.executor_address, + self.chain, + self.config, + )?)), _ => Err(EncodingError::FatalError(format!( "Unknown protocol system: {}", self.protocol_system diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 370f638..b38a3cf 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -570,9 +570,14 @@ pub struct MaverickV2SwapEncoder { } impl SwapEncoder for MaverickV2SwapEncoder { - fn new(executor_address: String) -> Self { - Self { executor_address } + fn new( + executor_address: String, + _chain: Chain, + _config: Option>, + ) -> Result { + Ok(Self { executor_address }) } + fn encode_swap( &self, swap: Swap, @@ -1451,12 +1456,17 @@ mod tests { // The receiver was generated with `makeAddr("bob") using forge` receiver: Bytes::from("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"), exact_out: false, - router_address: Bytes::zero(20), + router_address: Some(Bytes::default()), group_token_in: token_in.clone(), group_token_out: token_out.clone(), }; - let encoder = - MaverickV2SwapEncoder::new(String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4")); + let encoder = MaverickV2SwapEncoder::new( + String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), + TychoCoreChain::Ethereum.into(), + None, + ) + .unwrap(); + let encoded_swap = encoder .encode_swap(swap, encoding_context) .unwrap(); From 0ff4aef0c748bc7865e9dde3c263641847159542 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 29 Apr 2025 10:23:47 +0100 Subject: [PATCH 07/19] chore: Write encoding rust calldata to file and read in solidity test This way we can automatically replace the calldata when something changes. We don't need to manually replace the string ourselves. --- don't change below this line --- ENG-4453 Took 3 hours 26 minutes --- Cargo.lock | 37 ++++++--- foundry/foundry.toml | 2 +- foundry/test/TestUtils.sol | 29 +++++++ .../test/TychoRouterProtocolIntegration.t.sol | 41 ++++----- foundry/test/TychoRouterSequentialSwap.t.sol | 47 +++++------ foundry/test/TychoRouterSingleSwap.t.sol | 34 ++++---- foundry/test/TychoRouterSplitSwap.t.sol | 22 ++--- foundry/test/TychoRouterTestSetup.sol | 3 +- foundry/test/assets/calldata.txt | 26 ++++++ .../test/executors/BalancerV2Executor.t.sol | 10 +-- foundry/test/executors/EkuboExecutor.t.sol | 15 ++-- .../test/executors/UniswapV2Executor.t.sol | 2 - .../test/executors/UniswapV4Executor.t.sol | 14 ++-- .../evm/strategy_encoder/strategy_encoders.rs | 83 ++++++++++++------- .../evm/swap_encoder/swap_encoders.rs | 11 ++- src/encoding/evm/utils.rs | 54 +++++++++++- 16 files changed, 277 insertions(+), 153 deletions(-) create mode 100644 foundry/test/TestUtils.sol create mode 100644 foundry/test/assets/calldata.txt diff --git a/Cargo.lock b/Cargo.lock index 4106bac..7cce6e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,19 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler2" version = "2.0.0" @@ -1164,17 +1170,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", + "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", - "windows-targets 0.52.6", ] [[package]] @@ -1792,7 +1798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.8", ] [[package]] @@ -2006,9 +2012,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -2710,6 +2716,15 @@ dependencies = [ "unicase", ] +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "miniz_oxide" version = "0.8.8" @@ -2841,9 +2856,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] diff --git a/foundry/foundry.toml b/foundry/foundry.toml index 26d12dc..9acffad 100644 --- a/foundry/foundry.toml +++ b/foundry/foundry.toml @@ -7,6 +7,7 @@ evm_version = 'cancun' optimizer = true optimizer_runs = 200 via_ir = true +fs_permissions = [{ access = "read", path = "./test/assets" }] [profile.production] src = 'src' @@ -21,6 +22,5 @@ via_ir = true [rpc_endpoints] mainnet = "${RPC_URL}" - [fmt] line_length = 80 \ No newline at end of file diff --git a/foundry/test/TestUtils.sol b/foundry/test/TestUtils.sol new file mode 100644 index 0000000..3399c9f --- /dev/null +++ b/foundry/test/TestUtils.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.10; + +import "forge-std/Test.sol"; + +contract TestUtils is Test { + constructor() {} + + function loadCallDataFromFile(string memory testName) + internal + view + returns (bytes memory) + { + string memory fileContent = vm.readFile("./test/assets/calldata.txt"); + string[] memory lines = vm.split(fileContent, "\n"); + + for (uint256 i = 0; i < lines.length; i++) { + string[] memory parts = vm.split(lines[i], ":"); + if ( + parts.length >= 2 + && keccak256(bytes(parts[0])) == keccak256(bytes(testName)) + ) { + return vm.parseBytes(parts[1]); + } + } + + revert("Test calldata not found"); + } +} diff --git a/foundry/test/TychoRouterProtocolIntegration.t.sol b/foundry/test/TychoRouterProtocolIntegration.t.sol index 684c384..08eb97b 100644 --- a/foundry/test/TychoRouterProtocolIntegration.t.sol +++ b/foundry/test/TychoRouterProtocolIntegration.t.sol @@ -103,10 +103,9 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_sequential_encoding_strategy_usv4` - (bool success,) = tychoRouterAddr.call( - hex"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006828a8d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680122e10000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000412fb2c4e85c1b2236aef343641c10f81e4abfd675f520d86778cb9db16c9f500d11fe28b99285dd1bef082b9ccde3360a8077c57ece0775677fddfd5ff11b6e081c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d008b0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d23119330002cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_sequential_encoding_strategy_usv4"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -127,10 +126,8 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { // 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" - ); + bytes memory callData = loadCallDataFromFile("test_multi_protocol"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -150,10 +147,9 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { deal(ALICE, 1 ether); uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE); - // Encoded solution generated using `test_single_encoding_strategy_usv4_eth_in` - (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000007e0a55d4322a6e93c2379c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f92ce00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068080cd600000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041006930677d9715fb8c55f73546d3aaff4176ee1342b9b7ae34431a4356fc98a915f3103639d8e34cbaa591a3493e887dad6e816228200dee0a693408b4fa6fdc1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cf62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_encoding_strategy_usv4_eth_in"); + (bool success,) = tychoRouterAddr.call{value: 1 ether}(callData); vm.stopPrank(); @@ -177,10 +173,9 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_single_encoding_strategy_usv4_eth_out` - (bool success,) = tychoRouterAddr.call( - hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006828a8d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680122e1000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041bf1373f3d3943e0865f8081b1569b4deb66b56b8690500c4c9f1c1f7e1299510720e3d4c92abf6ec75f0b14a87b92957fd43408562f26b8616857469f94012e21b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000002cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c00000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_encoding_strategy_usv4_eth_out"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -199,10 +194,9 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); - // Encoded solution generated using `test_single_encoding_strategy_ekubo` - (bool success,) = address(tychoRouter).call{value: 1 ether}( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000071a0cb889707d426a7a386870a03bc70d1b069759805cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_encoding_strategy_ekubo"); + (bool success,) = tychoRouterAddr.call{value: 1 ether}(callData); uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); @@ -216,10 +210,9 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { vm.startPrank(ALICE); IERC20(UWU_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_single_encoding_strategy_curve` - (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000691d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e710201000103cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_encoding_strategy_curve"); + (bool success,) = tychoRouterAddr.call(callData); assertTrue(success, "Call Failed"); assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 2877855391767); diff --git a/foundry/test/TychoRouterSequentialSwap.t.sol b/foundry/test/TychoRouterSequentialSwap.t.sol index 2530a0a..1d44076 100644 --- a/foundry/test/TychoRouterSequentialSwap.t.sol +++ b/foundry/test/TychoRouterSequentialSwap.t.sol @@ -351,10 +351,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_sequential_swap_strategy_encoder` - (bool success,) = tychoRouterAddr.call( - hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682714ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067ff8eb300000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412fe66c22814eb271e37bb03303bae445eb96aa50fae9680a0ae685ee5795aebf1f5bb7718154c69680bcfc00cc9be525b2b021f57a1bddb4db622139acd425d41b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_sequential_swap_strategy_encoder"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -375,10 +374,10 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_sequential_swap_strategy_encoder_no_permit2` - (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000" + bytes memory callData = loadCallDataFromFile( + "test_sequential_swap_strategy_encoder_no_permit2" ); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -396,10 +395,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_sequential_strategy_cyclic_swap` - (bool success,) = tychoRouterAddr.call( - hex"51bcc7b60000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ec8f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682f96a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000000000000000000000000000680810ab00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000415de1a1f5644d780aa3e22af583e87639ff7d519518576da5b10c15748d75d7f64b9d4fc2439869fc226ca4a8b69c6cc4b284427b0d5d73c72e54f115cdf2bbca1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640010200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_sequential_strategy_cyclic_swap"); + (bool success,) = tychoRouterAddr.call(callData); assertTrue(success, "Call Failed"); assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99792554); @@ -417,10 +415,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_uniswap_v3_uniswap_v2` - (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb8004375dff511095cc5a197a54140a24efef3a416cbcdf9626bc03e24f779434178a73a0b4bad62ed000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010500" - ); + bytes memory callData = + loadCallDataFromFile("test_uniswap_v3_uniswap_v2"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -441,10 +438,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_uniswap_v3_uniswap_v3` - (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed000100692e234dae75c793f67a35089c9d99245e1c58470b2260fac5e5542a773aa44fbcfedf7c193bc2c599a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc299ac8ca7087fa4a2a1fb6357269965a2014abc35010000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_uniswap_v3_uniswap_v3"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -465,10 +461,8 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_uniswap_v3_curve` - (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed000100691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae460301000105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000" - ); + bytes memory callData = loadCallDataFromFile("test_uniswap_v3_curve"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -489,10 +483,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_uniswap_v3_curve` - (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c80072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e004375dff511095cc5a197a54140a24efef3a416010300525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_balancer_v2_uniswap_v2"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); diff --git a/foundry/test/TychoRouterSingleSwap.t.sol b/foundry/test/TychoRouterSingleSwap.t.sol index b0fe140..bf49fbd 100644 --- a/foundry/test/TychoRouterSingleSwap.t.sol +++ b/foundry/test/TychoRouterSingleSwap.t.sol @@ -294,10 +294,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); - // Encoded solution generated using `test_single_swap_strategy_encoder_no_permit2` - (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200010000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_swap_strategy_encoder_no_permit2"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -313,10 +312,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_single_swap_strategy_encoder` - (bool success,) = tychoRouterAddr.call( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006b56051582a970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f946a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068080e7200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041c0ace69971589bd5136c309c83a06d60a7a54a49a2f1cecdf51cc5aecd4f7cce07a1b4a152d758fb6c3e4a73f8cf96ca3b3e8ab82b402733b7979a67021e99a51c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200020000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_swap_strategy_encoder"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -333,10 +331,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); - // Encoded solution generated using `test_single_swap_strategy_encoder_wrap` - (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000059fb7d3830e6fc064b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682f965f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006808106700000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041cdef1c27d45a13adde80b5d93c8786741b69ddbe7684c4356f3dc7d4aa8029cb3cba0aac801787a7993ba0be72a6b459fa2a5c18a8e4938a0ccd3503d1be81841c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_swap_strategy_encoder_wrap"); + (bool success,) = tychoRouterAddr.call{value: 1 ether}(callData); vm.stopPrank(); @@ -355,10 +352,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_single_swap_strategy_encoder_unwrap` - (bool success,) = tychoRouterAddr.call( - hex"30ace1b10000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be0000000000000000000000000000000000000000000000000000000000000682db45d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068062e6500000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041de45f1a73e8a22fc958af300f93cff06b49e74667bb29b810aed4254fef0dae6340ceb95265d81f5b158bcade2b5a2e3efa8bfa521a6466c0b1ce0bcfddc19d21c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501020000000000000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_single_swap_strategy_encoder_unwrap"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); @@ -374,10 +370,10 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { uint256 balanceBefore = IERC20(DAI_ADDR).balanceOf(ALICE); vm.startPrank(ALICE); - // Encoded solution generated using `test_single_swap_strategy_encoder_no_transfer_in` - (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" + bytes memory callData = loadCallDataFromFile( + "test_single_swap_strategy_encoder_no_transfer_in" ); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); diff --git a/foundry/test/TychoRouterSplitSwap.t.sol b/foundry/test/TychoRouterSplitSwap.t.sol index 5246542..417b350 100644 --- a/foundry/test/TychoRouterSplitSwap.t.sol +++ b/foundry/test/TychoRouterSplitSwap.t.sol @@ -529,11 +529,9 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_split_swap_strategy_encoder` - (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010000000000000000000000000000000000000000000000000000000000" - ); - + bytes memory callData = + loadCallDataFromFile("test_split_swap_strategy_encoder"); + (bool success,) = tychoRouterAddr.call(callData); vm.stopPrank(); uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); @@ -552,10 +550,9 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_split_input_cyclic_swap` - (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_split_input_cyclic_swap"); + (bool success,) = tychoRouterAddr.call(callData); assertTrue(success, "Call Failed"); assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99654537); @@ -569,10 +566,9 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_split_output_cyclic_swap` - (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005e703f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682f963200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006808103a0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c46b497d6f01110f05257114b978d2fd2d493ac8dae2c7892bbfa593fc5d062384590828248348fe87b234c3417e463f12d4732e287a56882841a92bc41e9121b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000" - ); + bytes memory callData = + loadCallDataFromFile("test_split_output_cyclic_swap"); + (bool success,) = tychoRouterAddr.call(callData); assertTrue(success, "Call Failed"); assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99444510); diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index 8aa79e9..7757d49 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -14,6 +14,7 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; import {WETH} from "../lib/permit2/lib/solmate/src/tokens/WETH.sol"; import {Permit2TestHelper} from "./Permit2TestHelper.sol"; +import "./TestUtils.sol"; contract TychoRouterExposed is TychoRouter { constructor(address _permit2, address weth) TychoRouter(_permit2, weth) {} @@ -42,7 +43,7 @@ contract TychoRouterExposed is TychoRouter { } } -contract TychoRouterTestSetup is Constants, Permit2TestHelper { +contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils { TychoRouterExposed tychoRouter; address tychoRouterAddr; UniswapV2Executor public usv2Executor; diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt new file mode 100644 index 0000000..bf5c417 --- /dev/null +++ b/foundry/test/assets/calldata.txt @@ -0,0 +1,26 @@ +test_uniswap_v3_uniswap_v2:e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb8004375dff511095cc5a197a54140a24efef3a416cbcdf9626bc03e24f779434178a73a0b4bad62ed000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010500 +test_single_encoding_strategy_ekubo:20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000071a0cb889707d426a7a386870a03bc70d1b069759805cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000000000000000000000000000000000 +test_uniswap_v3_uniswap_v3:e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed000100692e234dae75c793f67a35089c9d99245e1c58470b2260fac5e5542a773aa44fbcfedf7c193bc2c599a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc299ac8ca7087fa4a2a1fb6357269965a2014abc35010000000000000000000000 +test_balancer_v2_uniswap_v2:e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c80072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e004375dff511095cc5a197a54140a24efef3a416010300525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000 +test_sequential_swap_strategy_encoder_no_permit2:e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000 +test_sequential_encoding_strategy_usv4:51bcc7b6000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006838268800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000004182b5da1843c415fd1304215c3049ced9c5e9b1f66463d5b035d67eb6fe8903de2564f5cb6740cdd838d7e497c61a75ccc572273a67e8c4b9e63f5f1ffc31e3bb1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000880086f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d23119330002cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f4000000000000000000000000000000000000000000000000 +test_single_encoding_strategy_usv4_eth_out:7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006838268800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a0900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000418b43338a724ecb56c3c2ba7b10f26445ef901fa89fb585ad97771b24b87b2d71627d7dcd178bce3594dff4e4c024bd34c64ca33eda7ed6419c627e9a9b089e591c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000002cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c00000000000000000000000000 +test_sequential_swap_strategy_encoder:51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006838268800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000411ddba9e27afa444896a84afcbd773cd492da98731f40e28243bf0aae4f345b7d44b7a6d220f7e5345055b7fe382114f0bf9f1ddb9e97987515880311f25f001b1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d940004375dff511095cc5a197a54140a24efef3a416000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20105000000000000000000000000000000000000000000000000 +test_single_swap_strategy_encoder_no_permit2:20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200010000000000000000000000000000 +test_single_swap_strategy_encoder_no_transfer_in:20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000058e7926ee858a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 +test_single_encoding_strategy_usv4_eth_in:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000007e0a55d4322a6e93c2379c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006838268800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041657dbf542ed8b39f717c204413c77002d0d75fb3f81300bfef8eedf5889b55523868c42c0e2ef53fe7b82229ceceabe1b662201898043519d042e333c7492dad1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cf62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000000000000000000000000000000000000000 +test_sequential_strategy_cyclic_swap:51bcc7b60000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ec8f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006838268800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041de5b09c674e85fef9de204fd3a03e190b1d06ebb6847543298183db02b46c0123c1433aec9951dfa391bc489c756816c4e87851882c8b4adbd21931490a820781b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640010200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000000000 +test_single_encoding_strategy_curve_st_eth:20144a070000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000691d1499e622d69689cdf9004d05ec547d650ff211eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeae7ab96520de3a18e5e111b5eaab095312d7fe84dc24316b9ae028f1497c275eb9192a3ea0f670220100010005cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000 +test_single_swap_strategy_encoder:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006b56051582a970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041df0cad7d6d1228221ff55af2259877bbc38b6ef4af79f90757eab0576601a2f522e27881b929a5053eccb0d2fddc18db0bf3e905e407b5f17461e1bf64cbe70e1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200020000000000000000000000000000 +test_single_encoding_strategy_curve:20144a070000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000691d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e710201000103cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000 +test_single_swap_strategy_encoder_unwrap:30ace1b10000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09100000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000004148c4a9386769cda15972ca351ee585b996d184bcf3539441f103ca8477ddc35b4f34e91f490a181166440ceabe512ecc71bd00615ef5ba0ac5a7c58f2e0653511c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501020000000000000000000000000000 +test_single_swap_strategy_encoder_wrap:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000059fb7d3830e6fc064b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041ca7017e254f4fc333dbe49435283ee7d7bbf0ab261f79a3606848abbc7387dc2563fcdb32e670f1f80e729326d8d9973aef060a7f7e28d9c8ec2420cad05aa6f1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 +test_split_output_cyclic_swap:7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005e703f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09100000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004177fcc3f010414cde9910d59346b7cac5341063addb7f041740fd0851cff3cd914b8b63c61edabe968f912b2ed17f273221a995d049e5d198384b5dbd00edb2011c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000 +test_split_input_cyclic_swap:7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09100000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004177fcc3f010414cde9910d59346b7cac5341063addb7f041740fd0851cff3cd914b8b63c61edabe968f912b2ed17f273221a995d049e5d198384b5dbd00edb2011c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000 +test_split_swap_strategy_encoder:7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006838268900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a091000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041df0cad7d6d1228221ff55af2259877bbc38b6ef4af79f90757eab0576601a2f522e27881b929a5053eccb0d2fddc18db0bf3e905e407b5f17461e1bf64cbe70e1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010000000000000000000000000000000000000000000000000000000000 +test_uniswap_v3_curve:e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed000100691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae460301000105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000 +test_multi_protocol:51bcc7b600000000000000000000000000000000000000000000005150ae84a8cdf000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2958f36da71a9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000005150ae84a8cdf00000000000000000000000000000000000000000000000000000000000006838268a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006810a09200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041cf9d1ecdf2b9df43bdac811677440db893f99f04f5addb24c82b15d766c87e5c0091919a2c43ed9dc6fbd1237ce2bed73a3ea27cd638af11c1bb5673468e1d051b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021400525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501020072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e3ede3eca2a72b3aecc820e955b36f38437d01395010500691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae4603010001053ede3eca2a72b3aecc820e955b36f38437d013950071a0cb889707d426a7a386870a03bc70d1b0697598003ede3eca2a72b3aecc820e955b36f38437d01395dac17f958d2ee523a2206206994597c13d831ec7a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001a36e2eb1c43200000032006cf62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c000000000000000000000000 +test_encode_balancer_v2:c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0105 +test_ekubo_encode_swap_multi:00ca4f73fe97d0b987a0d12b39bbd562c779bab6f60000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000001a36e2eb1c43200000032 +test_encode_uniswap_v4_sequential_swap:4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c +test_encode_uniswap_v4_simple_swap:4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec7000064000001 diff --git a/foundry/test/executors/BalancerV2Executor.t.sol b/foundry/test/executors/BalancerV2Executor.t.sol index 78b435b..1ad790e 100644 --- a/foundry/test/executors/BalancerV2Executor.t.sol +++ b/foundry/test/executors/BalancerV2Executor.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.26; +import "../TestUtils.sol"; import "@src/executors/BalancerV2Executor.sol"; -import {Test} from "../../lib/forge-std/src/Test.sol"; import {Constants} from "../Constants.sol"; contract BalancerV2ExecutorExposed is BalancerV2Executor { @@ -24,7 +24,7 @@ contract BalancerV2ExecutorExposed is BalancerV2Executor { } } -contract BalancerV2ExecutorTest is Test, Constants { +contract BalancerV2ExecutorTest is Constants, TestUtils { using SafeERC20 for IERC20; BalancerV2ExecutorExposed balancerV2Exposed; @@ -96,10 +96,8 @@ contract BalancerV2ExecutorTest is Test, Constants { } function testDecodeIntegration() public view { - // Generated by the SwapEncoder - test_encode_balancer_v2 bytes memory protocolData = - hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0105"; - + loadCallDataFromFile("test_encode_balancer_v2"); ( IERC20 tokenIn, IERC20 tokenOut, @@ -120,7 +118,7 @@ contract BalancerV2ExecutorTest is Test, Constants { function testSwapIntegration() public { // Generated by the SwapEncoder - test_encode_balancer_v2 bytes memory protocolData = - hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0105"; + loadCallDataFromFile("test_encode_balancer_v2"); uint256 amountIn = 10 ** 18; deal(WETH_ADDR, address(balancerV2Exposed), amountIn); diff --git a/foundry/test/executors/EkuboExecutor.t.sol b/foundry/test/executors/EkuboExecutor.t.sol index 9a6a9be..23996f9 100644 --- a/foundry/test/executors/EkuboExecutor.t.sol +++ b/foundry/test/executors/EkuboExecutor.t.sol @@ -1,14 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.26; -import {EkuboExecutor, TokenTransfer} from "@src/executors/EkuboExecutor.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "../TestUtils.sol"; import {Constants} from "../Constants.sol"; -import {Test, console} from "forge-std/Test.sol"; -import {NATIVE_TOKEN_ADDRESS} from "@ekubo/math/constants.sol"; +import {EkuboExecutor, TokenTransfer} from "@src/executors/EkuboExecutor.sol"; import {ICore} from "@ekubo/interfaces/ICore.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {NATIVE_TOKEN_ADDRESS} from "@ekubo/math/constants.sol"; +import {console} from "forge-std/Test.sol"; -contract EkuboExecutorTest is Test, Constants { +contract EkuboExecutorTest is Constants, TestUtils { address constant EXECUTOR_ADDRESS = 0xcA4F73Fe97D0B987a0D12B39BBD562c779BAb6f6; // Same address as in swap_encoder.rs tests EkuboExecutor executor; @@ -154,8 +155,6 @@ contract EkuboExecutorTest is Test, Constants { // Data is generated by test case in swap_encoder::tests::ekubo::test_encode_swap_multi function testMultiHopSwapIntegration() public { - multiHopSwap( - hex"00ca4f73fe97d0b987a0d12b39bbd562c779bab6f60000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000001a36e2eb1c43200000032" - ); + multiHopSwap(loadCallDataFromFile("test_ekubo_encode_swap_multi")); } } diff --git a/foundry/test/executors/UniswapV2Executor.t.sol b/foundry/test/executors/UniswapV2Executor.t.sol index ea0d825..5f81427 100644 --- a/foundry/test/executors/UniswapV2Executor.t.sol +++ b/foundry/test/executors/UniswapV2Executor.t.sol @@ -247,7 +247,6 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper { } function testDecodeIntegration() public view { - // Generated by the ExecutorStrategyEncoder - test_executor_strategy_encode bytes memory protocolData = hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc288e6a0c2ddd26feeb64f039a2c41296fcb3f564000000000000000000000000000000000000000010000"; @@ -268,7 +267,6 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper { } function testSwapIntegration() public { - // Generated by the ExecutorStrategyEncoder - test_executor_strategy_encode bytes memory protocolData = hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb111d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0000"; uint256 amountIn = 10 ** 18; diff --git a/foundry/test/executors/UniswapV4Executor.t.sol b/foundry/test/executors/UniswapV4Executor.t.sol index 17acd0a..8f2c292 100644 --- a/foundry/test/executors/UniswapV4Executor.t.sol +++ b/foundry/test/executors/UniswapV4Executor.t.sol @@ -2,12 +2,13 @@ pragma solidity ^0.8.26; import "../../src/executors/UniswapV4Executor.sol"; +import "../TestUtils.sol"; import "./UniswapV4Utils.sol"; +import "@src/executors/TokenTransfer.sol"; import "@src/executors/UniswapV4Executor.sol"; import {Constants} from "../Constants.sol"; -import {Test} from "../../lib/forge-std/src/Test.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; -import "@src/executors/TokenTransfer.sol"; +import {Test} from "../../lib/forge-std/src/Test.sol"; contract UniswapV4ExecutorExposed is UniswapV4Executor { constructor(IPoolManager _poolManager, address _permit2) @@ -30,7 +31,7 @@ contract UniswapV4ExecutorExposed is UniswapV4Executor { } } -contract UniswapV4ExecutorTest is Test, Constants { +contract UniswapV4ExecutorTest is Constants, TestUtils { using SafeERC20 for IERC20; UniswapV4ExecutorExposed uniswapV4Exposed; @@ -130,9 +131,8 @@ contract UniswapV4ExecutorTest is Test, Constants { function testSingleSwapIntegration() public { // USDE -> USDT - // Generated by the Tycho swap encoder - test_encode_uniswap_v4_simple_swap bytes memory protocolData = - hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec7000064000001"; + loadCallDataFromFile("test_encode_uniswap_v4_simple_swap"); uint256 amountIn = 100 ether; deal(USDE_ADDR, address(uniswapV4Exposed), amountIn); uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager); @@ -188,10 +188,8 @@ contract UniswapV4ExecutorTest is Test, Constants { function testMultipleSwapIntegration() public { // USDE -> USDT -> WBTC - // Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap - bytes memory protocolData = - hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c"; + loadCallDataFromFile("test_encode_uniswap_v4_sequential_swap"); uint256 amountIn = 100 ether; deal(USDE_ADDR, address(uniswapV4Exposed), amountIn); diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 674a81a..34f2a47 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -654,7 +654,7 @@ mod tests { }; use super::*; - use crate::encoding::models::Swap; + use crate::encoding::{evm::utils::write_calldata_to_file, models::Swap}; fn eth_chain() -> Chain { TychoCommonChain::Ethereum.into() @@ -735,9 +735,9 @@ mod tests { given_token: weth, given_amount: BigUint::from_str("1_000000000000000000").unwrap(), checked_token: dai, - expected_amount, + expected_amount: expected_amount.clone(), slippage, - checked_amount, + checked_amount: checked_amount.clone(), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), swaps: vec![swap], @@ -776,10 +776,16 @@ mod tests { "0000000000000000000000000000", // padding )); let hex_calldata = encode(&calldata); - println!("test_single_swap_strategy_encoder: {hex_calldata}"); assert_eq!(hex_calldata[..456], expected_input); assert_eq!(hex_calldata[1224..], expected_swap); + if expected_amount.is_some() & slippage.is_some() & checked_amount.is_none() { + // only write to file for 1 test case + write_calldata_to_file( + "test_single_swap_strategy_encoder", + &hex_calldata.to_string(), + ); + } } #[test] @@ -858,7 +864,10 @@ mod tests { let hex_calldata = encode(&calldata); assert_eq!(hex_calldata, expected_input); - println!("test_single_swap_strategy_encoder_no_permit2: {hex_calldata}"); + write_calldata_to_file( + "test_single_swap_strategy_encoder_no_permit2", + hex_calldata.as_str(), + ); } #[test] @@ -937,7 +946,10 @@ mod tests { let hex_calldata = encode(&calldata); assert_eq!(hex_calldata, expected_input); - println!("test_single_swap_strategy_encoder_no_transfer_in: {hex_calldata}"); + write_calldata_to_file( + "test_single_swap_strategy_encoder_no_transfer_in", + hex_calldata.as_str(), + ); } #[test] @@ -990,7 +1002,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_single_swap_strategy_encoder_wrap: {hex_calldata}"); + write_calldata_to_file("test_single_swap_strategy_encoder_wrap", hex_calldata.as_str()); } #[test] @@ -1043,7 +1055,10 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_split_swap_strategy_encoder_unwrap: {hex_calldata}"); + write_calldata_to_file( + "test_single_swap_strategy_encoder_unwrap", + hex_calldata.as_str(), + ); } } @@ -1114,7 +1129,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_sequential_swap_strategy_encoder: {hex_calldata}"); + write_calldata_to_file("test_sequential_swap_strategy_encoder", hex_calldata.as_str()); } #[test] @@ -1174,7 +1189,6 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_sequential_swap_strategy_encoder_no_permit2: {hex_calldata}"); let expected = String::from(concat!( "e8a980d7", /* function selector */ @@ -1208,6 +1222,10 @@ mod tests { )); assert_eq!(hex_calldata, expected); + write_calldata_to_file( + "test_sequential_swap_strategy_encoder_no_permit2", + hex_calldata.as_str(), + ); } #[test] @@ -1334,7 +1352,7 @@ mod tests { assert_eq!(hex_calldata[..456], expected_input); assert_eq!(hex_calldata[1224..], expected_swaps); - println!("test_cyclic_sequential_swap_split_strategy: {hex_calldata}"); + write_calldata_to_file("test_sequential_strategy_cyclic_swap", hex_calldata.as_str()); } mod optimized_transfers { @@ -1412,7 +1430,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_uniswap_v3_uniswap_v2: {hex_calldata}"); + write_calldata_to_file("test_uniswap_v3_uniswap_v2", hex_calldata.as_str()); } #[test] @@ -1494,7 +1512,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_uniswap_v3_uniswap_v3: {hex_calldata}"); + write_calldata_to_file("test_uniswap_v3_uniswap_v3", hex_calldata.as_str()); } #[test] @@ -1580,7 +1598,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_uniswap_v3_curve: {hex_calldata}"); + write_calldata_to_file("test_uniswap_v3_curve", hex_calldata.as_str()); } #[test] @@ -1647,7 +1665,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_balancer_v2_uniswap_v2: {hex_calldata}"); + write_calldata_to_file("test_balancer_v2_uniswap_v2", hex_calldata.as_str()); } #[test] @@ -1796,7 +1814,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("multi_protocol: {hex_calldata}"); + write_calldata_to_file("test_multi_protocol", hex_calldata.as_str()); } } } @@ -1895,7 +1913,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_split_swap_strategy_encoder: {hex_calldata}"); + write_calldata_to_file("test_split_swap_strategy_encoder", hex_calldata.as_str()); } #[test] @@ -2062,7 +2080,7 @@ mod tests { .join(""); assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("test_split_input_cyclic_swap: {hex_calldata}"); + write_calldata_to_file("test_split_input_cyclic_swap", hex_calldata.as_str()); } #[test] @@ -2227,13 +2245,13 @@ mod tests { assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("test_split_output_cyclic_swap: {hex_calldata}"); + write_calldata_to_file("test_split_output_cyclic_swap", hex_calldata.as_str()); } } mod protocol_integration { - // in this module we test protocol specific logic by creating the calldata that then is used - // in the solidity tests + // in this module we test protocol specific logic by creating the calldata that then is + // used in the solidity tests use super::*; #[test] @@ -2297,7 +2315,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_single_encoding_strategy_ekubo: {hex_calldata}"); + write_calldata_to_file("test_single_encoding_strategy_ekubo", hex_calldata.as_str()); } #[test] @@ -2362,7 +2380,10 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_single_encoding_strategy_usv4_eth_in: {hex_calldata}"); + write_calldata_to_file( + "test_single_encoding_strategy_usv4_eth_in", + hex_calldata.as_str(), + ); } #[test] @@ -2431,7 +2452,10 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_single_encoding_strategy_usv4_eth_out: {hex_calldata}"); + write_calldata_to_file( + "test_single_encoding_strategy_usv4_eth_out", + hex_calldata.as_str(), + ); } #[test] @@ -2560,7 +2584,7 @@ mod tests { assert_eq!(hex_calldata[..456], expected_input); assert_eq!(hex_calldata[1224..], expected_swaps); - println!("test_sequential_encoding_strategy_usv4: {hex_calldata}"); + write_calldata_to_file("test_sequential_encoding_strategy_usv4", hex_calldata.as_str()); } #[test] @@ -2568,7 +2592,7 @@ mod tests { // UWU ──(curve 2 crypto pool)──> WETH let token_in = Bytes::from("0x55C08ca52497e2f1534B59E2917BF524D4765257"); // UWU - let token_out = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // USDC + let token_out = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // WETH let static_attributes = HashMap::from([( "factory".to_string(), @@ -2623,7 +2647,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_split_encoding_strategy_curve: {hex_calldata}"); + write_calldata_to_file("test_single_encoding_strategy_curve", hex_calldata.as_str()); } #[test] @@ -2686,7 +2710,10 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("test_single_encoding_strategy_curve_st_eth: {hex_calldata}"); + write_calldata_to_file( + "test_single_encoding_strategy_curve_st_eth", + hex_calldata.as_str(), + ); } } } diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index eeeb7ff..5e5a42a 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -721,6 +721,7 @@ mod tests { mod balancer_v2 { use super::*; + use crate::encoding::evm::utils::write_calldata_to_file; #[test] fn test_encode_balancer_v2() { @@ -779,11 +780,13 @@ mod tests { "05" )) ); + write_calldata_to_file("test_encode_balancer_v2", hex_swap.as_str()); } } mod uniswap_v4 { use super::*; + use crate::encoding::evm::utils::write_calldata_to_file; #[test] fn test_encode_uniswap_v4_simple_swap() { @@ -830,7 +833,6 @@ mod tests { .encode_swap(swap, encoding_context) .unwrap(); let hex_swap = encode(&encoded_swap); - println!("test_encode_uniswap_v4_simple_swap: {hex_swap}"); assert_eq!( hex_swap, @@ -854,6 +856,7 @@ mod tests { "000001" )) ); + write_calldata_to_file("test_encode_uniswap_v4_simple_swap", hex_swap.as_str()); } #[test] @@ -1001,7 +1004,6 @@ mod tests { let combined_hex = format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap)); - println!("test_encode_uniswap_v4_sequential_swap: {combined_hex}"); assert_eq!( combined_hex, String::from(concat!( @@ -1030,11 +1032,12 @@ mod tests { "00003c" )) ); - println!("{combined_hex}") + write_calldata_to_file("test_encode_uniswap_v4_sequential_swap", combined_hex.as_str()); } } mod ekubo { use super::*; + use crate::encoding::evm::utils::write_calldata_to_file; const RECEIVER: &str = "ca4f73fe97d0b987a0d12b39bbd562c779bab6f6"; // Random address @@ -1159,7 +1162,6 @@ mod tests { let combined_hex = format!("{}{}", encode(first_encoded_swap), encode(second_encoded_swap)); - println!("{combined_hex}"); assert_eq!( combined_hex, // transfer type @@ -1180,6 +1182,7 @@ mod tests { "00000000000000000000000000000000000000000001a36e2eb1c43200000032", ), ); + write_calldata_to_file("test_ekubo_encode_swap_multi", combined_hex.as_str()); } } diff --git a/src/encoding/evm/utils.rs b/src/encoding/evm/utils.rs index 33b6de0..20e821e 100644 --- a/src/encoding/evm/utils.rs +++ b/src/encoding/evm/utils.rs @@ -1,4 +1,10 @@ -use std::{cmp::max, env, sync::Arc}; +use std::{ + cmp::max, + env, + fs::OpenOptions, + io::{BufRead, BufReader, Write}, + sync::{Arc, Mutex}, +}; use alloy::{ providers::{ProviderBuilder, RootProvider}, @@ -7,6 +13,7 @@ use alloy::{ use alloy_primitives::{aliases::U24, keccak256, Address, FixedBytes, Keccak256, U256, U8}; use alloy_sol_types::SolValue; use num_bigint::BigUint; +use once_cell::sync::Lazy; use tokio::runtime::{Handle, Runtime}; use tycho_common::Bytes; @@ -164,6 +171,51 @@ pub fn ple_encode(action_data_array: Vec>) -> Vec { encoded_action_data } +static CALLDATA_WRITE_MUTEX: Lazy> = Lazy::new(|| Mutex::new(())); +// Function used in tests to write calldata to a file that then is used by the corresponding +// solidity tests. +pub fn write_calldata_to_file(test_identifier: &str, hex_calldata: &str) { + let _lock = CALLDATA_WRITE_MUTEX + .lock() + .expect("Couldn't acquire lock"); + + let file_path = "foundry/test/assets/calldata.txt"; + let file = OpenOptions::new() + .read(true) + .open(file_path) + .expect("Failed to open calldata file for reading"); + let reader = BufReader::new(file); + + let mut lines = Vec::new(); + let mut found = false; + for line in reader.lines().map_while(Result::ok) { + let mut parts = line.splitn(2, ':'); // split at the : + let key = parts.next().unwrap_or(""); + if key == test_identifier { + lines.push(format!("{test_identifier}:{hex_calldata}")); + found = true; + } else { + lines.push(line); + } + } + + // If the test identifier wasn't found, append a new line + if !found { + lines.push(format!("{test_identifier}:{hex_calldata}")); + } + + // Write the updated contents back to the file + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .open(file_path) + .expect("Failed to open calldata file for writing"); + + for line in lines { + writeln!(file, "{line}").expect("Failed to write calldata"); + } +} + #[cfg(test)] mod tests { use num_bigint::BigUint; From 1746fd0e1d6678c63b0a9b9fbb67c1a0e4d4c8f9 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 29 Apr 2025 10:34:35 +0100 Subject: [PATCH 08/19] chore: Add "Report a vulnerability" to README --- don't change below this line --- ENG-4453 Took 8 minutes --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 5abdbea..eec77c7 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,7 @@ For complete documentation, see Tycho docs [here](https://docs.propellerheads.xy To get started on encoding, have a look at our [Encoding example](examples/encoding-example/README.md). For a complete example please refer to the [Tycho Quickstart guide](https://docs.propellerheads.xyz/tycho). + +## Report a Vulnerability + +Contact [security@propellerheads.xyz](mailto:security@propellerheads.xyz) \ No newline at end of file From bcef8f69f628c3a37a7cb5462e26200ad5aab1ee Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Tue, 29 Apr 2025 15:36:21 -0400 Subject: [PATCH 09/19] feat: Transfer Optimizations in MaverickV2 - Also added integration test to test the optimizations, where we can see the in and out transfers being optimized if we enable verbose foundry testing - Fixed typo in swap encoder builder initialization --- config/test_executor_addresses.json | 3 +- foundry/src/executors/MaverickV2Executor.sol | 24 ++++++-- .../test/TychoRouterProtocolIntegration.t.sol | 21 +++++++ foundry/test/TychoRouterTestSetup.sol | 7 ++- foundry/test/assets/calldata.txt | 1 + .../test/executors/MaverickV2Executor.t.sol | 60 ++++++++++++++----- src/encoding/evm/constants.rs | 3 +- .../evm/strategy_encoder/strategy_encoders.rs | 50 ++++++++++++++++ src/encoding/evm/swap_encoder/builder.rs | 2 +- .../evm/swap_encoder/swap_encoders.rs | 5 ++ 10 files changed, 152 insertions(+), 24 deletions(-) diff --git a/config/test_executor_addresses.json b/config/test_executor_addresses.json index 8c6dc5c..d04630d 100644 --- a/config/test_executor_addresses.json +++ b/config/test_executor_addresses.json @@ -8,6 +8,7 @@ "uniswap_v4": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", "vm:balancer_v2": "0xc7183455a4C133Ae270771860664b6B7ec320bB1", "ekubo_v2": "0xa0Cb889707d426A7A386870A03bc70d1b0697598", - "vm:curve": "0x1d1499e622D69689cdf9004d05Ec547d650Ff211" + "vm:curve": "0x1d1499e622D69689cdf9004d05Ec547d650Ff211", + "vm:maverick_v2": "0xA4AD4f68d0b91CFD19687c881e50f3A00242828c" } } diff --git a/foundry/src/executors/MaverickV2Executor.sol b/foundry/src/executors/MaverickV2Executor.sol index 08c0350..0775177 100644 --- a/foundry/src/executors/MaverickV2Executor.sol +++ b/foundry/src/executors/MaverickV2Executor.sol @@ -3,18 +3,19 @@ pragma solidity ^0.8.26; import "@interfaces/IExecutor.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "./TokenTransfer.sol"; error MaverickV2Executor__InvalidDataLength(); error MaverickV2Executor__InvalidTarget(); error MaverickV2Executor__InvalidFactory(); -contract MaverickV2Executor is IExecutor { +contract MaverickV2Executor is IExecutor, TokenTransfer { using SafeERC20 for IERC20; address public immutable factory; address private immutable self; - constructor(address _factory) { + constructor(address _factory, address _permit2) TokenTransfer(_permit2) { if (_factory == address(0)) { revert MaverickV2Executor__InvalidFactory(); } @@ -31,8 +32,9 @@ contract MaverickV2Executor is IExecutor { address target; address receiver; IERC20 tokenIn; + TransferType transferType; - (tokenIn, target, receiver) = _decodeData(data); + (tokenIn, target, receiver, transferType) = _decodeData(data); _verifyPairAddress(target); IMaverickV2Pool pool = IMaverickV2Pool(target); @@ -46,21 +48,31 @@ contract MaverickV2Executor is IExecutor { exactOutput: false, tickLimit: tickLimit }); - IERC20(tokenIn).safeTransfer(target, givenAmount); + + _transfer( + address(tokenIn), msg.sender, target, givenAmount, transferType + ); + // slither-disable-next-line unused-return (, calculatedAmount) = pool.swap(receiver, swapParams, ""); } function _decodeData(bytes calldata data) internal pure - returns (IERC20 inToken, address target, address receiver) + returns ( + IERC20 inToken, + address target, + address receiver, + TransferType transferType + ) { - if (data.length != 60) { + if (data.length != 61) { revert MaverickV2Executor__InvalidDataLength(); } inToken = IERC20(address(bytes20(data[0:20]))); target = address(bytes20(data[20:40])); receiver = address(bytes20(data[40:60])); + transferType = TransferType(uint8(data[60])); } function _verifyPairAddress(address target) internal view { diff --git a/foundry/test/TychoRouterProtocolIntegration.t.sol b/foundry/test/TychoRouterProtocolIntegration.t.sol index 08eb97b..baf8c9d 100644 --- a/foundry/test/TychoRouterProtocolIntegration.t.sol +++ b/foundry/test/TychoRouterProtocolIntegration.t.sol @@ -186,6 +186,27 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { assertEq(balanceAfter - balanceBefore, 1474406268748155809); } + function testSingleMaverickIntegration() public { + vm.stopPrank(); + + deal(GHO_ADDR, ALICE, 1 ether); + uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE); + + // Approve permit2 + vm.startPrank(ALICE); + IERC20(GHO_ADDR).approve(tychoRouterAddr, type(uint256).max); + + bytes memory callData = + loadCallDataFromFile("test_single_encoding_strategy_maverick"); + (bool success,) = tychoRouterAddr.call(callData); + + uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); + + assertTrue(success, "Call Failed"); + assertGe(balanceAfter - balanceBefore, 999725); + assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); + } + function testSingleEkuboIntegration() public { vm.stopPrank(); diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index 7757d49..540027c 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -15,6 +15,7 @@ import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; import {WETH} from "../lib/permit2/lib/solmate/src/tokens/WETH.sol"; import {Permit2TestHelper} from "./Permit2TestHelper.sol"; import "./TestUtils.sol"; +import {MaverickV2Executor} from "../src/executors/MaverickV2Executor.sol"; contract TychoRouterExposed is TychoRouter { constructor(address _permit2, address weth) TychoRouter(_permit2, weth) {} @@ -53,6 +54,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils { BalancerV2Executor public balancerv2Executor; EkuboExecutor public ekuboExecutor; CurveExecutor public curveExecutor; + MaverickV2Executor public maverickv2Executor; MockERC20[] tokens; function setUp() public { @@ -110,8 +112,10 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils { balancerv2Executor = new BalancerV2Executor(PERMIT2_ADDRESS); ekuboExecutor = new EkuboExecutor(ekuboCore, PERMIT2_ADDRESS); curveExecutor = new CurveExecutor(ETH_ADDR_FOR_CURVE, PERMIT2_ADDRESS); + maverickv2Executor = + new MaverickV2Executor(MAVERICK_V2_FACTORY, PERMIT2_ADDRESS); - address[] memory executors = new address[](7); + address[] memory executors = new address[](8); executors[0] = address(usv2Executor); executors[1] = address(usv3Executor); executors[2] = address(pancakev3Executor); @@ -119,6 +123,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils { executors[4] = address(balancerv2Executor); executors[5] = address(ekuboExecutor); executors[6] = address(curveExecutor); + executors[7] = address(maverickv2Executor); return executors; } diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index bf5c417..320a1fd 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -24,3 +24,4 @@ test_encode_balancer_v2:c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754 test_ekubo_encode_swap_multi:00ca4f73fe97d0b987a0d12b39bbd562c779bab6f60000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000001a36e2eb1c43200000032 test_encode_uniswap_v4_sequential_swap:4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c test_encode_uniswap_v4_simple_swap:4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec7000064000001 +test_single_encoding_strategy_maverick:20144a070000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000051a4ad4f68d0b91cfd19687c881e50f3a00242828c40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c67cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc201000000000000000000000000000000 diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol index dcba37c..ba08663 100644 --- a/foundry/test/executors/MaverickV2Executor.t.sol +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -6,12 +6,19 @@ import {Test} from "../../lib/forge-std/src/Test.sol"; import {Constants} from "../Constants.sol"; contract MaverickV2ExecutorExposed is MaverickV2Executor { - constructor(address _factory) MaverickV2Executor(_factory) {} + constructor(address _factory, address _permit2) + MaverickV2Executor(_factory, _permit2) + {} function decodeParams(bytes calldata data) external pure - returns (IERC20 tokenIn, address target, address receiver) + returns ( + IERC20 tokenIn, + address target, + address receiver, + TransferType transferType + ) { return _decodeData(data); } @@ -27,24 +34,37 @@ contract MaverickV2ExecutorTest is Test, Constants { function setUp() public { uint256 forkBlock = 22096000; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); - maverickV2Exposed = new MaverickV2ExecutorExposed(MAVERICK_V2_FACTORY); + maverickV2Exposed = + new MaverickV2ExecutorExposed(MAVERICK_V2_FACTORY, PERMIT2_ADDRESS); } function testDecodeParams() public view { - bytes memory params = - abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2)); + bytes memory params = abi.encodePacked( + GHO_ADDR, + GHO_USDC_POOL, + address(2), + TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL + ); - (IERC20 tokenIn, address target, address receiver) = - maverickV2Exposed.decodeParams(params); + ( + IERC20 tokenIn, + address target, + address receiver, + TokenTransfer.TransferType transferType + ) = maverickV2Exposed.decodeParams(params); assertEq(address(tokenIn), GHO_ADDR); assertEq(target, GHO_USDC_POOL); assertEq(receiver, address(2)); + assertEq( + uint8(transferType), + uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL) + ); } function testDecodeParamsInvalidDataLength() public { bytes memory invalidParams = - abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2), true); + abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, address(2)); vm.expectRevert(MaverickV2Executor__InvalidDataLength.selector); maverickV2Exposed.decodeParams(invalidParams); @@ -52,8 +72,12 @@ contract MaverickV2ExecutorTest is Test, Constants { function testSwap() public { uint256 amountIn = 10e18; - bytes memory protocolData = - abi.encodePacked(GHO_ADDR, GHO_USDC_POOL, BOB); + bytes memory protocolData = abi.encodePacked( + GHO_ADDR, + GHO_USDC_POOL, + BOB, + TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL + ); deal(GHO_ADDR, address(maverickV2Exposed), amountIn); uint256 balanceBefore = USDC.balanceOf(BOB); @@ -68,20 +92,28 @@ contract MaverickV2ExecutorTest is Test, Constants { function testDecodeIntegration() public view { // Generated by the SwapEncoder - test_encode_maverick_v2 bytes memory protocolData = - hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"; + hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e00"; - (IERC20 tokenIn, address pool, address receiver) = - maverickV2Exposed.decodeParams(protocolData); + ( + IERC20 tokenIn, + address pool, + address receiver, + TokenTransfer.TransferType transferType + ) = maverickV2Exposed.decodeParams(protocolData); assertEq(address(tokenIn), GHO_ADDR); assertEq(pool, GHO_USDC_POOL); assertEq(receiver, BOB); + assertEq( + uint8(transferType), + uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL) + ); } function testSwapIntegration() public { // Generated by the SwapEncoder - test_encode_maverick_v2 bytes memory protocolData = - hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e"; + hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e00"; uint256 amountIn = 10 ** 18; deal(GHO_ADDR, address(maverickV2Exposed), amountIn); diff --git a/src/encoding/evm/constants.rs b/src/encoding/evm/constants.rs index 37d8aff..2777040 100644 --- a/src/encoding/evm/constants.rs +++ b/src/encoding/evm/constants.rs @@ -20,7 +20,7 @@ pub static GROUPABLE_PROTOCOLS: LazyLock> = LazyLock::new( /// These protocols need an external in transfer to the pool. This transfer can be from the router, /// from the user or from the previous pool. Any protocols that are not defined here expect funds to -/// be in the router at the time of swap and do the transfer themselves from msg.sender +/// be in the router at the time of swap and do the transfer themselves from `msg.sender` pub static IN_TRANSFER_REQUIRED_PROTOCOLS: LazyLock> = LazyLock::new(|| { let mut set = HashSet::new(); set.insert("uniswap_v2"); @@ -30,6 +30,7 @@ pub static IN_TRANSFER_REQUIRED_PROTOCOLS: LazyLock> = Laz set.insert("pancakeswap_v3"); set.insert("uniswap_v4"); set.insert("ekubo_v2"); + set.insert("vm:maverick_v2"); set }); diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 34f2a47..24cba3a 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -2318,6 +2318,56 @@ mod tests { write_calldata_to_file("test_single_encoding_strategy_ekubo", hex_calldata.as_str()); } + #[test] + fn test_single_encoding_strategy_maverick() { + // GHO -> (maverick) -> USDC + let maverick_pool = ProtocolComponent { + id: String::from("0x14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67"), + protocol_system: String::from("vm:maverick_v2"), + ..Default::default() + }; + let token_in = Bytes::from("0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f"); + let token_out = Bytes::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + let swap = Swap { + component: maverick_pool, + token_in: token_in.clone(), + token_out: token_out.clone(), + split: 0f64, + }; + + let swap_encoder_registry = get_swap_encoder_registry(); + let encoder = SingleSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + None, + Bytes::from_str("0xA4AD4f68d0b91CFD19687c881e50f3A00242828c").unwrap(), + false, + ) + .unwrap(); + + let solution = Solution { + exact_out: false, + given_token: token_in, + given_amount: BigUint::from_str("1_000000000000000000").unwrap(), + checked_token: token_out, + expected_amount: None, + checked_amount: Some(BigUint::from_str("1000").unwrap()), + slippage: None, + // Alice + sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + swaps: vec![swap], + ..Default::default() + }; + + let (calldata, _) = encoder + .encode_strategy(solution) + .unwrap(); + + let hex_calldata = encode(&calldata); + write_calldata_to_file("test_single_encoding_strategy_maverick", hex_calldata.as_str()); + } + #[test] fn test_single_encoding_strategy_usv4_eth_in() { // Performs a single swap from ETH to PEPE using a USV4 pool diff --git a/src/encoding/evm/swap_encoder/builder.rs b/src/encoding/evm/swap_encoder/builder.rs index 735029c..9b4967c 100644 --- a/src/encoding/evm/swap_encoder/builder.rs +++ b/src/encoding/evm/swap_encoder/builder.rs @@ -76,7 +76,7 @@ impl SwapEncoderBuilder { "vm:curve" => { Ok(Box::new(CurveSwapEncoder::new(self.executor_address, self.chain, self.config)?)) } - "vm::maverick_v2" => Ok(Box::new(MaverickV2SwapEncoder::new( + "vm:maverick_v2" => Ok(Box::new(MaverickV2SwapEncoder::new( self.executor_address, self.chain, self.config, diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 9a82bfc..b419809 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -620,6 +620,7 @@ impl SwapEncoder for MaverickV2SwapEncoder { bytes_to_address(&swap.token_in)?, component_id, bytes_to_address(&encoding_context.receiver)?, + (encoding_context.transfer_type as u8).to_be_bytes(), ); Ok(args.abi_encode_packed()) } @@ -1545,6 +1546,7 @@ mod tests { #[test] fn test_encode_maverick_v2() { + // GHO -> (maverick) -> USDC let maverick_pool = ProtocolComponent { id: String::from("0x14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67"), protocol_system: String::from("vm:maverick_v2"), @@ -1565,6 +1567,7 @@ mod tests { router_address: Some(Bytes::default()), group_token_in: token_in.clone(), group_token_out: token_out.clone(), + transfer_type: TransferType::TransferToProtocol, }; let encoder = MaverickV2SwapEncoder::new( String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"), @@ -1587,6 +1590,8 @@ mod tests { "14Cf6D2Fe3E1B326114b07d22A6F6bb59e346c67", // receiver "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e", + // transfer from router to protocol + "00", )) .to_lowercase() ); From f99bd296a1b74900adc24ea9db7b75367612e0f9 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Tue, 29 Apr 2025 17:06:41 -0400 Subject: [PATCH 10/19] fix: Derive Clone in TychoEncoders --- src/encoding/evm/tycho_encoders.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/encoding/evm/tycho_encoders.rs b/src/encoding/evm/tycho_encoders.rs index c6c5692..3fd97c2 100644 --- a/src/encoding/evm/tycho_encoders.rs +++ b/src/encoding/evm/tycho_encoders.rs @@ -25,6 +25,7 @@ use crate::encoding::{ /// * `split_swap_strategy`: Encoder for split swaps /// * `native_address`: Address of the chain's native token /// * `wrapped_address`: Address of the chain's wrapped native token +#[derive(Clone)] pub struct TychoRouterEncoder { single_swap_strategy: SingleSwapStrategyEncoder, sequential_swap_strategy: SequentialSwapStrategyEncoder, @@ -213,6 +214,7 @@ impl TychoEncoder for TychoRouterEncoder { /// # Fields /// * `swap_encoder_registry`: Registry of swap encoders /// * `native_address`: Address of the chain's native token +#[derive(Clone)] pub struct TychoExecutorEncoder { swap_encoder_registry: SwapEncoderRegistry, native_address: Bytes, From d09497facad453c8d083ea33742215897399617a Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 30 Apr 2025 11:18:04 -0400 Subject: [PATCH 11/19] chore: Load maverick calldata from file - Also remove irrelevant comment --- foundry/test/TychoRouterProtocolIntegration.t.sol | 1 - foundry/test/assets/calldata.txt | 1 + foundry/test/executors/MaverickV2Executor.t.sol | 8 ++++---- src/encoding/evm/swap_encoder/swap_encoders.rs | 3 +++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/foundry/test/TychoRouterProtocolIntegration.t.sol b/foundry/test/TychoRouterProtocolIntegration.t.sol index baf8c9d..441c133 100644 --- a/foundry/test/TychoRouterProtocolIntegration.t.sol +++ b/foundry/test/TychoRouterProtocolIntegration.t.sol @@ -192,7 +192,6 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup { deal(GHO_ADDR, ALICE, 1 ether); uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE); - // Approve permit2 vm.startPrank(ALICE); IERC20(GHO_ADDR).approve(tychoRouterAddr, type(uint256).max); diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index 320a1fd..2ebfdc5 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -25,3 +25,4 @@ test_ekubo_encode_swap_multi:00ca4f73fe97d0b987a0d12b39bbd562c779bab6f6000000000 test_encode_uniswap_v4_sequential_swap:4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c test_encode_uniswap_v4_simple_swap:4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec7000064000001 test_single_encoding_strategy_maverick:20144a070000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000051a4ad4f68d0b91cfd19687c881e50f3a00242828c40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c67cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc201000000000000000000000000000000 +test_encode_maverick_v2:40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e00 diff --git a/foundry/test/executors/MaverickV2Executor.t.sol b/foundry/test/executors/MaverickV2Executor.t.sol index ba08663..755570d 100644 --- a/foundry/test/executors/MaverickV2Executor.t.sol +++ b/foundry/test/executors/MaverickV2Executor.t.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.26; import "@src/executors/MaverickV2Executor.sol"; -import {Test} from "../../lib/forge-std/src/Test.sol"; import {Constants} from "../Constants.sol"; +import "../TestUtils.sol"; contract MaverickV2ExecutorExposed is MaverickV2Executor { constructor(address _factory, address _permit2) @@ -24,7 +24,7 @@ contract MaverickV2ExecutorExposed is MaverickV2Executor { } } -contract MaverickV2ExecutorTest is Test, Constants { +contract MaverickV2ExecutorTest is TestUtils, Constants { using SafeERC20 for IERC20; MaverickV2ExecutorExposed maverickV2Exposed; @@ -92,7 +92,7 @@ contract MaverickV2ExecutorTest is Test, Constants { function testDecodeIntegration() public view { // Generated by the SwapEncoder - test_encode_maverick_v2 bytes memory protocolData = - hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e00"; + loadCallDataFromFile("test_encode_maverick_v2"); ( IERC20 tokenIn, @@ -113,7 +113,7 @@ contract MaverickV2ExecutorTest is Test, Constants { function testSwapIntegration() public { // Generated by the SwapEncoder - test_encode_maverick_v2 bytes memory protocolData = - hex"40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f14cf6d2fe3e1b326114b07d22a6f6bb59e346c671d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e00"; + loadCallDataFromFile("test_encode_maverick_v2"); uint256 amountIn = 10 ** 18; deal(GHO_ADDR, address(maverickV2Exposed), amountIn); diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index b419809..5fb82fe 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -643,6 +643,7 @@ mod tests { models::{protocol::ProtocolComponent, Chain as TychoCoreChain}, Bytes, }; + use crate::encoding::evm::utils::write_calldata_to_file; use super::*; use crate::encoding::models::TransferType; @@ -1595,5 +1596,7 @@ mod tests { )) .to_lowercase() ); + + write_calldata_to_file("test_encode_maverick_v2", hex_swap.as_str()); } } From 5f7ce7d5da67e6769ec8ec83964702faf7f164ec Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 30 Apr 2025 11:20:52 -0400 Subject: [PATCH 12/19] chore: nightly fmt --- src/encoding/evm/swap_encoder/swap_encoders.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 5fb82fe..5e74855 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -643,10 +643,9 @@ mod tests { models::{protocol::ProtocolComponent, Chain as TychoCoreChain}, Bytes, }; - use crate::encoding::evm::utils::write_calldata_to_file; use super::*; - use crate::encoding::models::TransferType; + use crate::encoding::{evm::utils::write_calldata_to_file, models::TransferType}; mod uniswap_v2 { use super::*; From 58e8e67494b02b67d4dca39a009b189f968161f3 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 30 Apr 2025 20:24:21 -0400 Subject: [PATCH 13/19] chore: dummy commit CI won't run --- src/encoding/tycho_encoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encoding/tycho_encoder.rs b/src/encoding/tycho_encoder.rs index 16e0bb0..b724c39 100644 --- a/src/encoding/tycho_encoder.rs +++ b/src/encoding/tycho_encoder.rs @@ -10,7 +10,7 @@ pub trait TychoEncoder { /// /// # Arguments /// * `solutions` - Vector of solutions to encode, each potentially using different setups (swap - /// paths, protocols, etc.) + /// paths, protocols, wrapping, etc.) /// /// # Returns /// * `Result, EncodingError>` - Vector of executable transactions From b43d5cad96da3adf6ac72658ba96a7c29e675c82 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 1 May 2025 00:39:21 +0000 Subject: [PATCH 14/19] chore(release): 0.85.0 [skip ci] ## [0.85.0](https://github.com/propeller-heads/tycho-execution/compare/0.84.0...0.85.0) (2025-05-01) ### Features * add mav executor ([0ac722d](https://github.com/propeller-heads/tycho-execution/commit/0ac722d91f6c2f7c09531f5f56f057d1fe014c6f)) * add swap encode ([72a651d](https://github.com/propeller-heads/tycho-execution/commit/72a651d453943d554722d0fa4818255fbec01ce5)) * Transfer Optimizations in MaverickV2 ([bcef8f6](https://github.com/propeller-heads/tycho-execution/commit/bcef8f69f628c3a37a7cb5462e26200ad5aab1ee)) ### Bug Fixes * add maverick for build ([bab30e3](https://github.com/propeller-heads/tycho-execution/commit/bab30e3958ee62091b322ac0bc540939c050ee9e)) * maverick test fork block ([4c93830](https://github.com/propeller-heads/tycho-execution/commit/4c938306bda62d37b8932697f98d0d667a96532b)) * swap test ([d103ca9](https://github.com/propeller-heads/tycho-execution/commit/d103ca9e33f931f18c8af79efa5d77d801bab2e9)) --- CHANGELOG.md | 16 ++++++++++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f1fa06..090e14e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [0.85.0](https://github.com/propeller-heads/tycho-execution/compare/0.84.0...0.85.0) (2025-05-01) + + +### Features + +* add mav executor ([0ac722d](https://github.com/propeller-heads/tycho-execution/commit/0ac722d91f6c2f7c09531f5f56f057d1fe014c6f)) +* add swap encode ([72a651d](https://github.com/propeller-heads/tycho-execution/commit/72a651d453943d554722d0fa4818255fbec01ce5)) +* Transfer Optimizations in MaverickV2 ([bcef8f6](https://github.com/propeller-heads/tycho-execution/commit/bcef8f69f628c3a37a7cb5462e26200ad5aab1ee)) + + +### Bug Fixes + +* add maverick for build ([bab30e3](https://github.com/propeller-heads/tycho-execution/commit/bab30e3958ee62091b322ac0bc540939c050ee9e)) +* maverick test fork block ([4c93830](https://github.com/propeller-heads/tycho-execution/commit/4c938306bda62d37b8932697f98d0d667a96532b)) +* swap test ([d103ca9](https://github.com/propeller-heads/tycho-execution/commit/d103ca9e33f931f18c8af79efa5d77d801bab2e9)) + ## [0.84.0](https://github.com/propeller-heads/tycho-execution/compare/0.83.0...0.84.0) (2025-04-28) diff --git a/Cargo.lock b/Cargo.lock index 7cce6e3..9762d0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4469,7 +4469,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.84.0" +version = "0.85.0" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index ff9d729..d438640 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.84.0" +version = "0.85.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 750382fc6fc689ad17673fe936e6b6e85e0d3abc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 1 May 2025 00:46:56 +0000 Subject: [PATCH 15/19] chore(release): 0.85.1 [skip ci] ## [0.85.1](https://github.com/propeller-heads/tycho-execution/compare/0.85.0...0.85.1) (2025-05-01) ### Bug Fixes * Derive Clone in TychoEncoders ([f99bd29](https://github.com/propeller-heads/tycho-execution/commit/f99bd296a1b74900adc24ea9db7b75367612e0f9)) --- 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 090e14e..8b18468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.85.1](https://github.com/propeller-heads/tycho-execution/compare/0.85.0...0.85.1) (2025-05-01) + + +### Bug Fixes + +* Derive Clone in TychoEncoders ([f99bd29](https://github.com/propeller-heads/tycho-execution/commit/f99bd296a1b74900adc24ea9db7b75367612e0f9)) + ## [0.85.0](https://github.com/propeller-heads/tycho-execution/compare/0.84.0...0.85.0) (2025-05-01) diff --git a/Cargo.lock b/Cargo.lock index 9762d0b..2d3a0b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4469,7 +4469,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.85.0" +version = "0.85.1" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index d438640..cc7298b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.85.0" +version = "0.85.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" From 8a7c39052d45ee75e81cbb267748a1fc635a8c34 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Fri, 2 May 2025 12:47:03 +0100 Subject: [PATCH 16/19] feat: Propagate the entire result of the callback --- don't change below this line --- ENG-4476 Took 41 minutes --- foundry/src/TychoRouter.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index 55be637..379f0e7 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -661,8 +661,8 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { bytes memory result = _callHandleCallbackOnExecutor(msg.data); // slither-disable-next-line assembly assembly ("memory-safe") { - // Propagate the calculatedAmount - return(add(result, 32), 16) + // Propagate the result + return(add(result, 32), mload(result)) } } From 04000059e5e7940f209639c900557b437a766913 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Fri, 2 May 2025 12:48:03 +0100 Subject: [PATCH 17/19] feat: Change revert condition in _wrapETH --- don't change below this line --- ENG-4476 Took 1 minute --- foundry/src/TychoRouter.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index 379f0e7..4d9d7b7 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -757,7 +757,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param amount of native ETH to wrap. */ function _wrapETH(uint256 amount) internal { - if (msg.value > 0 && msg.value != amount) { + if (msg.value != amount) { revert TychoRouter__MessageValueMismatch(msg.value, amount); } _weth.deposit{value: amount}(); From c4b9a1d76915baaa07e214c016d176374ff83179 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Fri, 2 May 2025 12:55:04 +0100 Subject: [PATCH 18/19] docs: Mention audits in the README --- don't change below this line --- ENG-4476 Took 6 minutes --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eec77c7..5f289da 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ For complete documentation, see Tycho docs [here](https://docs.propellerheads.xy To get started on encoding, have a look at our [Encoding example](examples/encoding-example/README.md). For a complete example please refer to the [Tycho Quickstart guide](https://docs.propellerheads.xyz/tycho). -## Report a Vulnerability +## Security + +All audits of the Tycho Router and Executor contracts can be found [here](docs/audits). +The vulnerabilities discovered during the audits have been acknowledged and addressed or accepted. + +### Report a Vulnerability Contact [security@propellerheads.xyz](mailto:security@propellerheads.xyz) \ No newline at end of file From aeaeff12fd4eb9602eb4fbff1c342b07485bfcc2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 May 2025 14:58:02 +0000 Subject: [PATCH 19/19] chore(release): 0.86.0 [skip ci] ## [0.86.0](https://github.com/propeller-heads/tycho-execution/compare/0.85.1...0.86.0) (2025-05-02) ### Features * Change revert condition in _wrapETH ([0400005](https://github.com/propeller-heads/tycho-execution/commit/04000059e5e7940f209639c900557b437a766913)) * Propagate the entire result of the callback ([8a7c390](https://github.com/propeller-heads/tycho-execution/commit/8a7c39052d45ee75e81cbb267748a1fc635a8c34)) --- CHANGELOG.md | 8 ++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b18468..ebb704f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [0.86.0](https://github.com/propeller-heads/tycho-execution/compare/0.85.1...0.86.0) (2025-05-02) + + +### Features + +* Change revert condition in _wrapETH ([0400005](https://github.com/propeller-heads/tycho-execution/commit/04000059e5e7940f209639c900557b437a766913)) +* Propagate the entire result of the callback ([8a7c390](https://github.com/propeller-heads/tycho-execution/commit/8a7c39052d45ee75e81cbb267748a1fc635a8c34)) + ## [0.85.1](https://github.com/propeller-heads/tycho-execution/compare/0.85.0...0.85.1) (2025-05-01) diff --git a/Cargo.lock b/Cargo.lock index 2d3a0b6..f89c5df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4469,7 +4469,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.85.1" +version = "0.86.0" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index cc7298b..a7a3f7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.85.1" +version = "0.86.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"