From 47d96c234776784cb42de31aa50fa75352b06efb Mon Sep 17 00:00:00 2001 From: die-herdplatte <173669014+die-herdplatte@users.noreply.github.com> Date: Wed, 26 Mar 2025 16:50:03 +0100 Subject: [PATCH] Add integration test --- foundry/test/executors/EkuboExecutor.t.sol | 44 ++++++++++----- .../evm/swap_encoder/swap_encoders.rs | 55 ++++++++++--------- 2 files changed, 59 insertions(+), 40 deletions(-) diff --git a/foundry/test/executors/EkuboExecutor.t.sol b/foundry/test/executors/EkuboExecutor.t.sol index c323bdb..d870352 100644 --- a/foundry/test/executors/EkuboExecutor.t.sol +++ b/foundry/test/executors/EkuboExecutor.t.sol @@ -9,6 +9,7 @@ import {NATIVE_TOKEN_ADDRESS} from "@ekubo/math/constants.sol"; import {ICore} from "@ekubo/interfaces/ICore.sol"; contract EkuboExecutorTest is Test, Constants { + address constant EXECUTOR_ADDRESS = 0xcA4F73Fe97D0B987a0D12B39BBD562c779BAb6f6; // Same address as in swap_encoder.rs tests EkuboExecutor executor; IERC20 USDC = IERC20(USDC_ADDR); @@ -19,9 +20,14 @@ contract EkuboExecutorTest is Test, Constants { bytes32 constant ORACLE_CONFIG = 0x51d02a5948496a67827242eabc5725531342527c000000000000000000000000; function setUp() public { - uint256 forkBlock = 22082754; - vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); - executor = new EkuboExecutor(ICore(payable(CORE_ADDRESS))); + vm.createSelectFork(vm.rpcUrl("mainnet"), 22082754); + + deployCodeTo( + "executors/EkuboExecutor.sol", + abi.encode(CORE_ADDRESS), + EXECUTOR_ADDRESS + ); + executor = EkuboExecutor(payable(EXECUTOR_ADDRESS)); } function testSingleSwapEth() public { @@ -86,7 +92,8 @@ contract EkuboExecutorTest is Test, Constants { assertEq(address(executor).balance, ethBalanceBeforeExecutor + amountOut); } - function testMultiHopSwap() public { + // Expects input that encodes the same test case as swap_encoder::tests::ekubo::test_encode_swap_multi + function multiHopSwap(bytes memory data) internal { uint256 amountIn = 1 ether; deal(address(executor), amountIn); @@ -97,15 +104,6 @@ contract EkuboExecutorTest is Test, Constants { uint256 usdtBalanceBeforeCore = USDT.balanceOf(CORE_ADDRESS); uint256 usdtBalanceBeforeExecutor = USDT.balanceOf(address(executor)); - bytes memory data = abi.encodePacked( - address(executor), // receiver - NATIVE_TOKEN_ADDRESS, // tokenIn - USDC_ADDR, // tokenOut of 1st swap - ORACLE_CONFIG, // config of 1st swap - USDT_ADDR, // tokenOut of 2nd swap - bytes32(0x00000000000000000000000000000000000000000001a36e2eb1c43200000032) // config of 2nd swap (0.0025% fee & 0.005% base pool) - ); - uint256 gasBefore = gasleft(); uint256 amountOut = executor.swap(amountIn, data); console.log(gasBefore - gasleft()); @@ -118,4 +116,24 @@ contract EkuboExecutorTest is Test, Constants { assertEq(USDT.balanceOf(CORE_ADDRESS), usdtBalanceBeforeCore - amountOut); assertEq(USDT.balanceOf(address(executor)), usdtBalanceBeforeExecutor + amountOut); } + + // Same test case as in swap_encoder::tests::ekubo::test_encode_swap_multi + function testMultiHopSwap() public { + bytes memory data = abi.encodePacked( + address(executor), // receiver + NATIVE_TOKEN_ADDRESS, // tokenIn + USDC_ADDR, // tokenOut of 1st swap + ORACLE_CONFIG, // config of 1st swap + USDT_ADDR, // tokenOut of 2nd swap + bytes32(0x00000000000000000000000000000000000000000001a36e2eb1c43200000032) // config of 2nd swap (0.0025% fee & 0.005% base pool) + ); + multiHopSwap(data); + } + + // Data is generated by test case in swap_encoder::tests::ekubo::test_encode_swap_multi + function testMultiHopSwapIntegration() public { + multiHopSwap( + hex"ca4f73fe97d0b987a0d12b39bbd562c779bab6f60000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000001a36e2eb1c43200000032" + ); + } } diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 447be6d..0938088 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -2,7 +2,6 @@ use std::str::FromStr; use alloy_primitives::{Address, Bytes as AlloyBytes}; use alloy_sol_types::SolValue; -use num_traits::Zero; use tycho_core::Bytes; use crate::encoding::{ @@ -705,6 +704,8 @@ mod tests { mod ekubo { use super::*; + const RECEIVER: &str = "ca4f73fe97d0b987a0d12b39bbd562c779bab6f6"; // Random address + #[test] fn test_encode_swap_simple() { let token_in = Bytes::from(Address::ZERO.as_slice()); @@ -729,7 +730,7 @@ mod tests { }; let encoding_context = EncodingContext { - receiver: "0xcA4F73Fe97D0B987a0D12B39BBD562c779BAb6f6".into(), // Random address + receiver: RECEIVER.into(), group_token_in: token_in.clone(), group_token_out: token_out.clone(), exact_out: false, @@ -746,16 +747,15 @@ mod tests { assert_eq!( hex_swap, - String::from(concat!( - // receiver - "ca4f73fe97d0b987a0d12b39bbd562c779bab6f6", - // group token in - "0000000000000000000000000000000000000000", - // token out 1st swap - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - // pool config 1st swap - "51d02a5948496a67827242eabc5725531342527c000000000000000000000000", - )) + RECEIVER.to_string() + + concat!( + // group token in + "0000000000000000000000000000000000000000", + // token out 1st swap + "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + // pool config 1st swap + "51d02a5948496a67827242eabc5725531342527c000000000000000000000000", + ), ); } @@ -768,7 +768,7 @@ mod tests { let encoder = EkuboSwapEncoder::new(String::default()); let encoding_context = EncodingContext { - receiver: "0xcA4F73Fe97D0B987a0D12B39BBD562c779BAb6f6".into(), // Random address + receiver: RECEIVER.into(), group_token_in: group_token_in.clone(), group_token_out: group_token_out.clone(), exact_out: false, @@ -818,22 +818,23 @@ mod tests { let combined_hex = format!("{}{}", encode(first_encoded_swap), encode(second_encoded_swap)); + println!("{}", combined_hex); + assert_eq!( combined_hex, - String::from(concat!( - // receiver - "ca4f73fe97d0b987a0d12b39bbd562c779bab6f6", - // group token in - "0000000000000000000000000000000000000000", - // token out 1st swap - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - // pool config 1st swap - "51d02a5948496a67827242eabc5725531342527c000000000000000000000000", - // token out 2nd swap - "dac17f958d2ee523a2206206994597c13d831ec7", - // pool config 2nd swap - "00000000000000000000000000000000000000000001a36e2eb1c43200000032", - )) + RECEIVER.to_string() + + concat!( + // group token in + "0000000000000000000000000000000000000000", + // token out 1st swap + "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + // pool config 1st swap + "51d02a5948496a67827242eabc5725531342527c000000000000000000000000", + // token out 2nd swap + "dac17f958d2ee523a2206206994597c13d831ec7", + // pool config 2nd swap + "00000000000000000000000000000000000000000001a36e2eb1c43200000032", + ), ); } }