From d2ba2554179ac374be2bac5863ca8f58f01a575d Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 8 Jul 2025 13:32:13 +0100 Subject: [PATCH 1/8] test: Add encoding test for a uniswap X integration test Took 26 minutes --- foundry/test/assets/calldata.txt | 1 + tests/uniswap_x_integration_tests.rs | 117 +++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 tests/uniswap_x_integration_tests.rs diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index 3aecf03..f8bca01 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -33,3 +33,4 @@ test_encode_balancer_v3:7bc3485026ac48b6cf9baf0a377477fff5703af8c71ea051a5f82c67 test_single_encoding_strategy_balancer_v3:5c4b639c0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000097ffedb80d4b2ca6105a07a4d90eb739c45a66600000000000000000000000030881baa943777f92dc934d53d3bfdf33382cab300000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006503a6a84cd762d9707a21605b548aaab891562aab097ffedb80d4b2ca6105a07a4d90eb739c45a66630881baa943777f92dc934d53d3bfdf33382cab3f028ac624074d6793c36dc8a06ecec0f5a39a71800cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000 test_uniswap_v3_balancer_v3:e21dd0d3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004a220e6096b25eadb88358cb44068a324825467500000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed0000006503a6a84cd762d9707a21605b548aaab891562aab2260fac5e5542a773aa44fbcfedf7c193bc2c5994a220e6096b25eadb88358cb44068a3248254675571bea0e99e139cd0b6b7d9352ca872dfe0d72dd01cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000 test_single_swap_strategy_encoder:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006d70b85442ed96492800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006880f27700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068596c7f00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000411d60a13b5e993ef8088cb2cb7e16281f47fbc329bd0ec2a48165e7898542a7ed12fe7ffdec713b6d94e99ddf0a384674617b6190b8534491d525ecb090c8e4881c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 +test_sequential_swap_unix:0101e21dd0d30000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb8004375dff511095cc5a197a54140a24efef3a416cbcdf9626bc03e24f779434178a73a0b4bad62ed000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010200 diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs new file mode 100644 index 0000000..b55bb90 --- /dev/null +++ b/tests/uniswap_x_integration_tests.rs @@ -0,0 +1,117 @@ +use std::{collections::HashMap, str::FromStr}; + +use alloy::{hex::encode, primitives::Address, sol_types::SolValue}; +use num_bigint::{BigInt, BigUint}; +use tycho_common::{models::protocol::ProtocolComponent, Bytes}; +use tycho_execution::encoding::{ + evm::{ + approvals::protocol_approvals_manager::ProtocolApprovalsManager, + utils::{bytes_to_address, write_calldata_to_file}, + }, + models::{Solution, Swap, UserTransferType}, +}; + +use crate::common::{ + encoding::encode_tycho_router_call, eth, eth_chain, get_tycho_router_encoder, router_address, + usdc, wbtc, weth, +}; + +mod common; + +#[test] +fn test_sequential_swap_unix() { + // Performs a sequential swap from WETH to USDC though WBTC using USV3 and USV2 + // pools + // + // WETH ───(USV3)──> WBTC ───(USV2)──> USDC + // Creates all the calldata needed for the uniswap X callbackData + + let filler = Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(); + let unix_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be").unwrap(); + + let weth = weth(); + let wbtc = wbtc(); + let usdc = usdc(); + + let swap_weth_wbtc = Swap { + component: ProtocolComponent { + id: "0xCBCdF9626bC03E24f779434178A73a0B4bad62eD".to_string(), + protocol_system: "uniswap_v3".to_string(), + static_attributes: { + let mut attrs = HashMap::new(); + attrs.insert( + "fee".to_string(), + Bytes::from(BigInt::from(3000).to_signed_bytes_be()), + ); + attrs + }, + ..Default::default() + }, + token_in: weth.clone(), + token_out: wbtc.clone(), + split: 0f64, + user_data: None, + }; + let swap_wbtc_usdc = Swap { + component: ProtocolComponent { + id: "0x004375Dff511095CC5A197A54140a24eFEF3A416".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: wbtc.clone(), + token_out: usdc.clone(), + split: 0f64, + user_data: None, + }; + let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom); + + let solution = Solution { + exact_out: false, + given_token: weth.clone(), + given_amount: BigUint::from_str("1_000000000000000000").unwrap(), + checked_token: usdc.clone(), + checked_amount: BigUint::from_str("26173932").unwrap(), + sender: filler.clone(), + receiver: filler.clone(), + swaps: vec![swap_weth_wbtc, swap_wbtc_usdc], + ..Default::default() + }; + + let encoded_solution = encoder + .encode_solutions(vec![solution.clone()]) + .unwrap()[0] + .clone(); + + let tycho_calldata = encode_tycho_router_call( + eth_chain().id, + encoded_solution, + &solution, + &UserTransferType::TransferFrom, + ð(), + None, + ) + .unwrap() + .data; + + // Uniswap X specific part + let filler_address = bytes_to_address(&filler).unwrap(); + let token_approvals_manager = ProtocolApprovalsManager::new().unwrap(); + + let token_in_approval_needed = token_approvals_manager + .approval_needed( + bytes_to_address(&weth).unwrap(), + filler_address, + bytes_to_address(&router_address()).unwrap(), + ) + .unwrap(); + + let token_out_approval_needed = token_approvals_manager + .approval_needed(bytes_to_address(&usdc).unwrap(), filler_address, unix_reactor) + .unwrap(); + + let full_calldata = + (token_in_approval_needed, token_out_approval_needed, tycho_calldata).abi_encode_packed(); + + let hex_calldata = encode(&full_calldata); + write_calldata_to_file("test_sequential_swap_unix", hex_calldata.as_str()); +} From 96d0bf4ba545e4ae369c292aec6b56a32cf77db0 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Wed, 9 Jul 2025 11:36:15 +0100 Subject: [PATCH 2/8] fix: Replicate a real Uniswap X order in integration test Took 16 minutes --- foundry/test/assets/calldata.txt | 2 +- tests/common/mod.rs | 4 +++ tests/uniswap_x_integration_tests.rs | 50 ++++++++++++++-------------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index f8bca01..5c45c3b 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -33,4 +33,4 @@ test_encode_balancer_v3:7bc3485026ac48b6cf9baf0a377477fff5703af8c71ea051a5f82c67 test_single_encoding_strategy_balancer_v3:5c4b639c0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000097ffedb80d4b2ca6105a07a4d90eb739c45a66600000000000000000000000030881baa943777f92dc934d53d3bfdf33382cab300000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006503a6a84cd762d9707a21605b548aaab891562aab097ffedb80d4b2ca6105a07a4d90eb739c45a66630881baa943777f92dc934d53d3bfdf33382cab3f028ac624074d6793c36dc8a06ecec0f5a39a71800cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000 test_uniswap_v3_balancer_v3:e21dd0d3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004a220e6096b25eadb88358cb44068a324825467500000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed0000006503a6a84cd762d9707a21605b548aaab891562aab2260fac5e5542a773aa44fbcfedf7c193bc2c5994a220e6096b25eadb88358cb44068a3248254675571bea0e99e139cd0b6b7d9352ca872dfe0d72dd01cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000 test_single_swap_strategy_encoder:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006d70b85442ed96492800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006880f27700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068596c7f00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000411d60a13b5e993ef8088cb2cb7e16281f47fbc329bd0ec2a48165e7898542a7ed12fe7ffdec713b6d94e99ddf0a384674617b6190b8534491d525ecb090c8e4881c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 -test_sequential_swap_unix:0101e21dd0d30000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb8004375dff511095cc5a197a54140a24efef3a416cbcdf9626bc03e24f779434178a73a0b4bad62ed000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010200 +test_sequential_swap_unix:0101e21dd0d300000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000769cfd8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470b6b175474e89094c44da98b954eedeac495271d0fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000643041cbd36888becc7bbcbc0045e3b1f144466f5f5777d92f208679db4b9778590fa3cab3ac9e2168010000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb483041cbd36888becc7bbcbc0045e3b1f144466f5fcd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010200 diff --git a/tests/common/mod.rs b/tests/common/mod.rs index b10ca13..9a0fb98 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -43,6 +43,10 @@ pub fn pepe() -> Bytes { Bytes::from_str("0x6982508145454Ce325dDbE47a25d4ec3d2311933").unwrap() } +pub fn usdt() -> Bytes { + Bytes::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap() +} + pub fn get_signer() -> PrivateKeySigner { // Set up a mock private key for signing (Alice's pk in our contract tests) let private_key = diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs index b55bb90..0c60a39 100644 --- a/tests/uniswap_x_integration_tests.rs +++ b/tests/uniswap_x_integration_tests.rs @@ -12,54 +12,54 @@ use tycho_execution::encoding::{ }; use crate::common::{ - encoding::encode_tycho_router_call, eth, eth_chain, get_tycho_router_encoder, router_address, - usdc, wbtc, weth, + dai, encoding::encode_tycho_router_call, eth, eth_chain, get_tycho_router_encoder, + router_address, usdc, usdt, }; mod common; #[test] fn test_sequential_swap_unix() { - // Performs a sequential swap from WETH to USDC though WBTC using USV3 and USV2 - // pools + // Replicates real uniswap X order settled in tx: + // 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d + // Performs a sequential + // swap from DAI to USDT though USDC using USV3 and USV2 pools // - // WETH ───(USV3)──> WBTC ───(USV2)──> USDC + // DAI ───(USV3)──> USDC ───(USV2)──> USDT // Creates all the calldata needed for the uniswap X callbackData let filler = Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(); let unix_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be").unwrap(); - let weth = weth(); - let wbtc = wbtc(); + let dai = dai(); let usdc = usdc(); + let usdt = usdt(); - let swap_weth_wbtc = Swap { + let swap_dai_usdc = Swap { component: ProtocolComponent { - id: "0xCBCdF9626bC03E24f779434178A73a0B4bad62eD".to_string(), + id: "0x5777d92f208679DB4b9778590Fa3CAB3aC9e2168".to_string(), protocol_system: "uniswap_v3".to_string(), static_attributes: { let mut attrs = HashMap::new(); - attrs.insert( - "fee".to_string(), - Bytes::from(BigInt::from(3000).to_signed_bytes_be()), - ); + attrs + .insert("fee".to_string(), Bytes::from(BigInt::from(100).to_signed_bytes_be())); attrs }, ..Default::default() }, - token_in: weth.clone(), - token_out: wbtc.clone(), + token_in: dai.clone(), + token_out: usdc.clone(), split: 0f64, user_data: None, }; - let swap_wbtc_usdc = Swap { + let swap_usdc_usdt = Swap { component: ProtocolComponent { - id: "0x004375Dff511095CC5A197A54140a24eFEF3A416".to_string(), + id: "0x3041CbD36888bECc7bbCBc0045E3B1f144466f5f".to_string(), protocol_system: "uniswap_v2".to_string(), ..Default::default() }, - token_in: wbtc.clone(), - token_out: usdc.clone(), + token_in: usdc.clone(), + token_out: usdt.clone(), split: 0f64, user_data: None, }; @@ -67,13 +67,13 @@ fn test_sequential_swap_unix() { let solution = Solution { exact_out: false, - given_token: weth.clone(), - given_amount: BigUint::from_str("1_000000000000000000").unwrap(), - checked_token: usdc.clone(), - checked_amount: BigUint::from_str("26173932").unwrap(), + given_token: dai.clone(), + given_amount: BigUint::from_str("2_000_000000000000000000").unwrap(), + checked_token: usdt.clone(), + checked_amount: BigUint::from_str("1_990_000000").unwrap(), sender: filler.clone(), receiver: filler.clone(), - swaps: vec![swap_weth_wbtc, swap_wbtc_usdc], + swaps: vec![swap_dai_usdc, swap_usdc_usdt], ..Default::default() }; @@ -99,7 +99,7 @@ fn test_sequential_swap_unix() { let token_in_approval_needed = token_approvals_manager .approval_needed( - bytes_to_address(&weth).unwrap(), + bytes_to_address(&dai).unwrap(), filler_address, bytes_to_address(&router_address()).unwrap(), ) From 4fef906e421d9595b388e463b4f28af1890dabe4 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 9 Jul 2025 15:44:41 -0400 Subject: [PATCH 3/8] test: Use calldata in USX integration test - Needed to update the filler address with the one from the test - Removed unnecessary approval from non-integration test. The approval is now performed in the callback method. --- foundry/test/assets/calldata.txt | 2 +- foundry/test/uniswap_x/UniswapXFiller.t.sol | 47 ++++++++++++++++++--- tests/uniswap_x_integration_tests.rs | 11 ++--- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index 5c45c3b..1bb2e40 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -33,4 +33,4 @@ test_encode_balancer_v3:7bc3485026ac48b6cf9baf0a377477fff5703af8c71ea051a5f82c67 test_single_encoding_strategy_balancer_v3:5c4b639c0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000097ffedb80d4b2ca6105a07a4d90eb739c45a66600000000000000000000000030881baa943777f92dc934d53d3bfdf33382cab300000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006503a6a84cd762d9707a21605b548aaab891562aab097ffedb80d4b2ca6105a07a4d90eb739c45a66630881baa943777f92dc934d53d3bfdf33382cab3f028ac624074d6793c36dc8a06ecec0f5a39a71800cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000 test_uniswap_v3_balancer_v3:e21dd0d3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004a220e6096b25eadb88358cb44068a324825467500000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed0000006503a6a84cd762d9707a21605b548aaab891562aab2260fac5e5542a773aa44fbcfedf7c193bc2c5994a220e6096b25eadb88358cb44068a3248254675571bea0e99e139cd0b6b7d9352ca872dfe0d72dd01cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000 test_single_swap_strategy_encoder:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006d70b85442ed96492800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006880f27700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068596c7f00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000411d60a13b5e993ef8088cb2cb7e16281f47fbc329bd0ec2a48165e7898542a7ed12fe7ffdec713b6d94e99ddf0a384674617b6190b8534491d525ecb090c8e4881c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 -test_sequential_swap_unix:0101e21dd0d300000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000769cfd8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470b6b175474e89094c44da98b954eedeac495271d0fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000643041cbd36888becc7bbcbc0045e3b1f144466f5f5777d92f208679db4b9778590fa3cab3ac9e2168010000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb483041cbd36888becc7bbcbc0045e3b1f144466f5fcd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010200 +test_sequential_swap_usx:0101e21dd0d300000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000769cfd80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d9da78b6a5bedca287aa5d49613ba36b90c15c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470b6b175474e89094c44da98b954eedeac495271d0fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000643041cbd36888becc7bbcbc0045e3b1f144466f5f5777d92f208679db4b9778590fa3cab3ac9e2168010000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb483041cbd36888becc7bbcbc0045e3b1f144466f5f6d9da78b6a5bedca287aa5d49613ba36b90c15c4010200 diff --git a/foundry/test/uniswap_x/UniswapXFiller.t.sol b/foundry/test/uniswap_x/UniswapXFiller.t.sol index 5128339..b473277 100644 --- a/foundry/test/uniswap_x/UniswapXFiller.t.sol +++ b/foundry/test/uniswap_x/UniswapXFiller.t.sol @@ -72,9 +72,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { abi.encodePacked(true, true, tychoRouterData); deal(WETH_ADDR, address(filler), amountIn); - vm.startPrank(address(filler)); - IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn); - vm.stopPrank(); + ResolvedOrder[] memory orders = new ResolvedOrder[](1); OutputToken[] memory outputs = new OutputToken[](1); outputs[0] = OutputToken({ @@ -82,7 +80,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { amount: 1847751195973566072891, recipient: BOB }); - // Mostly irrelevant fields for this test - we only need token input and outputs + // Irrelevant fields for this test - we only need token output // info for the sake of testing. orders[0] = ResolvedOrder({ info: OrderInfo({ @@ -96,7 +94,6 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { input: InputToken({ token: address(WETH_ADDR), amount: amountIn, - // We need the proper maxAmount for our approval to work maxAmount: amountIn }), outputs: outputs, @@ -119,7 +116,45 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { assertGe(IERC20(DAI_ADDR).balanceOf(BOB), amountOut); } - function testExecuteIntegration() public { + function testCallbackIntegration() public { + fillerSetup(); + deal(DAI_ADDR, address(filler), 2000 ether); + uint256 amountOut = 1994835180; + + ResolvedOrder[] memory orders = new ResolvedOrder[](1); + OutputToken[] memory outputs = new OutputToken[](1); + + outputs[0] = + OutputToken({token: address(USDT_ADDR), amount: 0, recipient: BOB}); + // Irrelevant fields for this test - we only need token output + // info for the sake of testing. + orders[0] = ResolvedOrder({ + info: OrderInfo({ + reactor: address(0), + swapper: address(0), + nonce: 0, + deadline: 0, + additionalValidationContract: address(0), + additionalValidationData: "" + }), + input: InputToken({token: address(DAI_ADDR), amount: 0, maxAmount: 0}), + outputs: outputs, + sig: "", + hash: "" + }); + bytes memory callbackData = + loadCallDataFromFile("test_sequential_swap_usx"); + + vm.startPrank(REACTOR); + filler.reactorCallback(orders, callbackData); + vm.stopPrank(); + + // Check that the funds are in the filler at the end of the function call + uint256 finalBalance = IERC20(USDT_ADDR).balanceOf(address(filler)); + assertGe(finalBalance, amountOut); + } + + function testExecute() public { fillerSetup(); // tx: 0x5b602b7d0a37e241bd032a907b9ddf314e9f2fc2104fd91cb55bdb3d8dfe4e9c // 0.2 WBTC -> USDC diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs index 0c60a39..e349b40 100644 --- a/tests/uniswap_x_integration_tests.rs +++ b/tests/uniswap_x_integration_tests.rs @@ -19,7 +19,7 @@ use crate::common::{ mod common; #[test] -fn test_sequential_swap_unix() { +fn test_sequential_swap_usx() { // Replicates real uniswap X order settled in tx: // 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d // Performs a sequential @@ -28,8 +28,9 @@ fn test_sequential_swap_unix() { // DAI ───(USV3)──> USDC ───(USV2)──> USDT // Creates all the calldata needed for the uniswap X callbackData - let filler = Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(); - let unix_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be").unwrap(); + let filler = Bytes::from_str("0x6D9da78B6A5BEdcA287AA5d49613bA36b90c15C4").unwrap(); + let usx_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be") + .unwrap(); let dai = dai(); let usdc = usdc(); @@ -106,12 +107,12 @@ fn test_sequential_swap_unix() { .unwrap(); let token_out_approval_needed = token_approvals_manager - .approval_needed(bytes_to_address(&usdc).unwrap(), filler_address, unix_reactor) + .approval_needed(bytes_to_address(&usdc).unwrap(), filler_address, usx_reactor) .unwrap(); let full_calldata = (token_in_approval_needed, token_out_approval_needed, tycho_calldata).abi_encode_packed(); let hex_calldata = encode(&full_calldata); - write_calldata_to_file("test_sequential_swap_unix", hex_calldata.as_str()); + write_calldata_to_file("test_sequential_swap_usx", hex_calldata.as_str()); } From 7cf8a7eeed91334c7b3eb6faaf155243dbad08d4 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Wed, 9 Jul 2025 15:47:43 -0400 Subject: [PATCH 4/8] chore: nightly fmt --- tests/uniswap_x_integration_tests.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs index e349b40..80c955a 100644 --- a/tests/uniswap_x_integration_tests.rs +++ b/tests/uniswap_x_integration_tests.rs @@ -29,8 +29,7 @@ fn test_sequential_swap_usx() { // Creates all the calldata needed for the uniswap X callbackData let filler = Bytes::from_str("0x6D9da78B6A5BEdcA287AA5d49613bA36b90c15C4").unwrap(); - let usx_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be") - .unwrap(); + let usx_reactor = Address::from_str("0x00000011F84B9aa48e5f8aA8B9897600006289Be").unwrap(); let dai = dai(); let usdc = usdc(); From 4ba59192fcfe60d6d4f95b9540a2a7d4da202952 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Fri, 11 Jul 2025 17:05:45 -0400 Subject: [PATCH 5/8] feat: add testExecuteIntegration - Needed to change the integration test setup to use two USV3 pools instead of one V3 and V2, since the V2 pool was taking too much fees for the order to be fulfilled. - Also needed to change the fork block to make this test work, which meant also needing to update the data for the existing testExecute. --- foundry/test/Constants.sol | 1 + foundry/test/assets/calldata.txt | 2 +- foundry/test/uniswap_x/UniswapXFiller.t.sol | 68 +++++++++++---------- tests/uniswap_x_integration_tests.rs | 12 +++- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/foundry/test/Constants.sol b/foundry/test/Constants.sol index cb81d58..c2ca63d 100644 --- a/foundry/test/Constants.sol +++ b/foundry/test/Constants.sol @@ -77,6 +77,7 @@ contract Constants is Test, BaseConstants { // Uniswap v3 address DAI_WETH_USV3 = 0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8; + address DAI_USDT_USV3 = 0x48DA0965ab2d2cbf1C17C09cFB5Cbe67Ad5B1406; address USDC_WETH_USV3 = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 0.05% fee address USDC_WETH_USV3_2 = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8; // 0.3% fee diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index 1bb2e40..730de23 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -33,4 +33,4 @@ test_encode_balancer_v3:7bc3485026ac48b6cf9baf0a377477fff5703af8c71ea051a5f82c67 test_single_encoding_strategy_balancer_v3:5c4b639c0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000097ffedb80d4b2ca6105a07a4d90eb739c45a66600000000000000000000000030881baa943777f92dc934d53d3bfdf33382cab300000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006503a6a84cd762d9707a21605b548aaab891562aab097ffedb80d4b2ca6105a07a4d90eb739c45a66630881baa943777f92dc934d53d3bfdf33382cab3f028ac624074d6793c36dc8a06ecec0f5a39a71800cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000 test_uniswap_v3_balancer_v3:e21dd0d3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004a220e6096b25eadb88358cb44068a324825467500000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d200692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed0000006503a6a84cd762d9707a21605b548aaab891562aab2260fac5e5542a773aa44fbcfedf7c193bc2c5994a220e6096b25eadb88358cb44068a3248254675571bea0e99e139cd0b6b7d9352ca872dfe0d72dd01cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000 test_single_swap_strategy_encoder:30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006d70b85442ed96492800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006880f27700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000068596c7f00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000411d60a13b5e993ef8088cb2cb7e16281f47fbc329bd0ec2a48165e7898542a7ed12fe7ffdec713b6d94e99ddf0a384674617b6190b8534491d525ecb090c8e4881c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000 -test_sequential_swap_usx:0101e21dd0d300000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000769cfd80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d9da78b6a5bedca287aa5d49613ba36b90c15c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000bf00692e234dae75c793f67a35089c9d99245e1c58470b6b175474e89094c44da98b954eedeac495271d0fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000643041cbd36888becc7bbcbc0045e3b1f144466f5f5777d92f208679db4b9778590fa3cab3ac9e2168010000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb483041cbd36888becc7bbcbc0045e3b1f144466f5f6d9da78b6a5bedca287aa5d49613ba36b90c15c4010200 +test_sequential_swap_usx:0101e21dd0d300000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000769cfd80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d9da78b6a5bedca287aa5d49613ba36b90c15c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470b6b175474e89094c44da98b954eedeac495271d0fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000643ede3eca2a72b3aecc820e955b36f38437d013955777d92f208679db4b9778590fa3cab3ac9e2168010000692e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48dac17f958d2ee523a2206206994597c13d831ec70000646d9da78b6a5bedca287aa5d49613ba36b90c15c43416cf6c708da44db2624d63ea0aaef7113527c6010100000000000000000000 diff --git a/foundry/test/uniswap_x/UniswapXFiller.t.sol b/foundry/test/uniswap_x/UniswapXFiller.t.sol index b473277..6522c84 100644 --- a/foundry/test/uniswap_x/UniswapXFiller.t.sol +++ b/foundry/test/uniswap_x/UniswapXFiller.t.sol @@ -6,7 +6,7 @@ import "@src/uniswap_x/UniswapXFiller.sol"; import "../TychoRouterTestSetup.sol"; contract UniswapXFillerTest is Test, TychoRouterTestSetup { - address EXECUTOR = makeAddr("executor"); + address EXECUTOR = address(0xCe79b081c0c924cb67848723ed3057234d10FC6b); address REACTOR = address(0x00000011F84B9aa48e5f8aA8B9897600006289Be); UniswapXFiller filler; @@ -18,7 +18,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { ); function getForkBlock() public pure override returns (uint256) { - return 22788691; + return 22880493; } function fillerSetup() public { @@ -116,46 +116,49 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { assertGe(IERC20(DAI_ADDR).balanceOf(BOB), amountOut); } - function testCallbackIntegration() public { + function testExecuteIntegration() public { fillerSetup(); - deal(DAI_ADDR, address(filler), 2000 ether); - uint256 amountOut = 1994835180; - ResolvedOrder[] memory orders = new ResolvedOrder[](1); - OutputToken[] memory outputs = new OutputToken[](1); + // Set to time with no more exclusivity penalty for not being exclusive filler + vm.warp(1752050415); - outputs[0] = - OutputToken({token: address(USDT_ADDR), amount: 0, recipient: BOB}); - // Irrelevant fields for this test - we only need token output - // info for the sake of testing. - orders[0] = ResolvedOrder({ - info: OrderInfo({ - reactor: address(0), - swapper: address(0), - nonce: 0, - deadline: 0, - additionalValidationContract: address(0), - additionalValidationData: "" - }), - input: InputToken({token: address(DAI_ADDR), amount: 0, maxAmount: 0}), - outputs: outputs, - sig: "", - hash: "" + deal( + DAI_ADDR, + address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852), + 2000 ether + ); + + uint256 amountIn = 2000000000000000000000; + + vm.startPrank(address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852)); + // Approve Permit2 + IERC20(DAI_ADDR).approve( + address(0x000000000022D473030F116dDEE9F6B43aC78BA3), amountIn + ); + vm.stopPrank(); + + // Tx 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d + // Calldata generated using rust test `test_sequential_swap_usx` + + SignedOrder memory order = SignedOrder({ + order: hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a61800000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e8520468320351debb1ddbfb032a239d699e3d54e3ce2b6e1037cd836a784c80b60100000000000000000000000000000000000000000000000000000000686e2bf9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000076f9f4870000000000000000000000000000000000000000000000000000000076566300000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e85200000000000000000000000000000000000000000000000000000000686e2aee00000000000000000000000000000000000000000000000000000000686e2b2a000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000007727b5f40000000000000000000000000000000000000000000000000000000000000041a2d261cd4c8930428260f18b55e3036024bac68d58cb2ee6161e6395b0984b827104158713d44ddc4e14d852b48d93d95a4e60b8d5be1ef431c1e82d2f76a4111b00000000000000000000000000000000000000000000000000000000000000", + sig: hex"f4cc5734820e4ee08519045c83a25b75687756053b3d6c0fda2141380dfa6ef17b40f64d9279f237e96982c6ba53a202e01a4358fd66e027c9bdf200d5626f441c" }); + bytes memory callbackData = loadCallDataFromFile("test_sequential_swap_usx"); - vm.startPrank(REACTOR); - filler.reactorCallback(orders, callbackData); + vm.startPrank(EXECUTOR); + filler.execute(order, callbackData); vm.stopPrank(); - - // Check that the funds are in the filler at the end of the function call - uint256 finalBalance = IERC20(USDT_ADDR).balanceOf(address(filler)); - assertGe(finalBalance, amountOut); } function testExecute() public { fillerSetup(); + + // Overwrite block so signature doesn't expire. + vm.rollFork(22788691); + // tx: 0x5b602b7d0a37e241bd032a907b9ddf314e9f2fc2104fd91cb55bdb3d8dfe4e9c // 0.2 WBTC -> USDC SignedOrder memory order = SignedOrder({ @@ -200,11 +203,12 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { vm.stopPrank(); // This is a hack because the tx we are trying to replicate returns a looooot more USDC than what the uni v2 pool does at this point - // 5113180081 is the difference and 54068100 is the fee - deal(USDC_ADDR, address(filler), 5113180081 + 54068100); + // 21613301393 is the difference and 54068100 is the fee + deal(USDC_ADDR, address(filler), 21613301393 + 54068100); vm.startPrank(EXECUTOR); filler.execute(order, callbackData); + console.logUint(IERC20(USDC_ADDR).balanceOf(address(filler))); vm.stopPrank(); } diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs index 80c955a..5200578 100644 --- a/tests/uniswap_x_integration_tests.rs +++ b/tests/uniswap_x_integration_tests.rs @@ -23,7 +23,7 @@ fn test_sequential_swap_usx() { // Replicates real uniswap X order settled in tx: // 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d // Performs a sequential - // swap from DAI to USDT though USDC using USV3 and USV2 pools + // swap from DAI to USDT though USDC using USV3 pools // // DAI ───(USV3)──> USDC ───(USV2)──> USDT // Creates all the calldata needed for the uniswap X callbackData @@ -54,8 +54,14 @@ fn test_sequential_swap_usx() { }; let swap_usdc_usdt = Swap { component: ProtocolComponent { - id: "0x3041CbD36888bECc7bbCBc0045E3B1f144466f5f".to_string(), - protocol_system: "uniswap_v2".to_string(), + id: "0x3416cF6C708Da44DB2624D63ea0AAef7113527C6".to_string(), + protocol_system: "uniswap_v3".to_string(), + static_attributes: { + let mut attrs = HashMap::new(); + attrs + .insert("fee".to_string(), Bytes::from(BigInt::from(100).to_signed_bytes_be())); + attrs + }, ..Default::default() }, token_in: usdc.clone(), From a53fa6502d588c6ee25e190f982c0d67055a0d27 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Fri, 11 Jul 2025 17:17:32 -0400 Subject: [PATCH 6/8] test: rewrite testExecute without hack - We can use the same transaction as the integration test, with a different low-fee USV3 pool. - Don't need to roll the fork either. --- foundry/test/uniswap_x/UniswapXFiller.t.sol | 36 ++++++++++----------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/foundry/test/uniswap_x/UniswapXFiller.t.sol b/foundry/test/uniswap_x/UniswapXFiller.t.sol index 6522c84..2c2583f 100644 --- a/foundry/test/uniswap_x/UniswapXFiller.t.sol +++ b/foundry/test/uniswap_x/UniswapXFiller.t.sol @@ -119,7 +119,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { function testExecuteIntegration() public { fillerSetup(); - // Set to time with no more exclusivity penalty for not being exclusive filler + // Set to time with no more penalty for not being exclusive filler vm.warp(1752050415); deal( @@ -153,37 +153,40 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { vm.stopPrank(); } - function testExecute() public { + function testExecutes() public { fillerSetup(); - // Overwrite block so signature doesn't expire. - vm.rollFork(22788691); + // Set to time with no more penalty for not being exclusive filler + vm.warp(1752050415); - // tx: 0x5b602b7d0a37e241bd032a907b9ddf314e9f2fc2104fd91cb55bdb3d8dfe4e9c - // 0.2 WBTC -> USDC + // tx: 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d + // DAI ──> USDT SignedOrder memory order = SignedOrder({ - order: hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a61800000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000001312d000000000000000000000000000000000000000000000000000000000001312d0000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be0000000000000000000000000d1100e55ef6c4e5800f4624b1e6121d798eb696046832163cef9c09382cf582bb878b37a42933ea2bdf33757942ab2747b3500100000000000000000000000000000000000000000000000000000000685d4150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000004f921447c00000000000000000000000000000000000000000000000000000004f1464dea0000000000000000000000000d1100e55ef6c4e5800f4624b1e6121d798eb696000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000330d86400000000000000000000000000000000000000000000000000000000032bce2600000000000000000000000027213e28d7fda5c57fe9e5dd923818dbccf71c4700000000000000000000000000000000000000000000000000000000685d407600000000000000000000000000000000000000000000000000000000685d40b2000000000000000000000000225a38bc71102999dd13478bfabd7c4d53f2dc170000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000004fb7f8815000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417067afde0759ae3653dad5d412519f488b6e9ed8955b3e3b8606e85c0198a9d71075295d33fe84b5ccc9c2d38a7ea79d7fad68128a37cabc5557342756a4e8311b00000000000000000000000000000000000000000000000000000000000000", - sig: hex"41b7a696a04f897d1e4ccaf88136092169c2874242d55c3fe4c028125efe95340f5ce764b9dce9d2cae241d97ceb515d3f1739972ca884ed51b2870045438c3a1c" + order: hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a61800000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e8520468320351debb1ddbfb032a239d699e3d54e3ce2b6e1037cd836a784c80b60100000000000000000000000000000000000000000000000000000000686e2bf9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000076f9f4870000000000000000000000000000000000000000000000000000000076566300000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e85200000000000000000000000000000000000000000000000000000000686e2aee00000000000000000000000000000000000000000000000000000000686e2b2a000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000007727b5f40000000000000000000000000000000000000000000000000000000000000041a2d261cd4c8930428260f18b55e3036024bac68d58cb2ee6161e6395b0984b827104158713d44ddc4e14d852b48d93d95a4e60b8d5be1ef431c1e82d2f76a4111b00000000000000000000000000000000000000000000000000000000000000", + sig: hex"f4cc5734820e4ee08519045c83a25b75687756053b3d6c0fda2141380dfa6ef17b40f64d9279f237e96982c6ba53a202e01a4358fd66e027c9bdf200d5626f441c" }); - uint256 amountIn = 0.2 * 10 ** 8; + uint256 amountIn = 2000000000000000000000; bool zeroForOne = true; + uint24 fee = 100; bytes memory protocolData = abi.encodePacked( - WBTC_ADDR, - USDC_WBTC_POOL, + DAI_ADDR, + USDT_ADDR, + fee, fillerAddr, + DAI_USDT_USV3, zeroForOne, RestrictTransferFrom.TransferType.TransferFrom ); bytes memory swap = - encodeSingleSwap(address(usv2Executor), protocolData); + encodeSingleSwap(address(usv3Executor), protocolData); bytes memory tychoRouterData = abi.encodeWithSelector( tychoRouter.singleSwap.selector, amountIn, - WBTC_ADDR, - USDC_ADDR, + DAI_ADDR, + USDT_ADDR, 1, false, false, @@ -202,13 +205,8 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { IERC20(WBTC_ADDR).approve(tychoRouterAddr, amountIn); vm.stopPrank(); - // This is a hack because the tx we are trying to replicate returns a looooot more USDC than what the uni v2 pool does at this point - // 21613301393 is the difference and 54068100 is the fee - deal(USDC_ADDR, address(filler), 21613301393 + 54068100); - vm.startPrank(EXECUTOR); filler.execute(order, callbackData); - console.logUint(IERC20(USDC_ADDR).balanceOf(address(filler))); vm.stopPrank(); } From a0531bdfadcd4691c6abdd3730a3b234d15b6219 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Fri, 11 Jul 2025 17:18:32 -0400 Subject: [PATCH 7/8] chore: typo fix --- foundry/test/uniswap_x/UniswapXFiller.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundry/test/uniswap_x/UniswapXFiller.t.sol b/foundry/test/uniswap_x/UniswapXFiller.t.sol index 2c2583f..be92ca3 100644 --- a/foundry/test/uniswap_x/UniswapXFiller.t.sol +++ b/foundry/test/uniswap_x/UniswapXFiller.t.sol @@ -153,7 +153,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup { vm.stopPrank(); } - function testExecutes() public { + function testExecute() public { fillerSetup(); // Set to time with no more penalty for not being exclusive filler From e775238b0816e71d383193bfdb0cbbfe64e37b7a Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Mon, 14 Jul 2025 11:29:03 -0400 Subject: [PATCH 8/8] fix: chain id call after main update --- tests/uniswap_x_integration_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/uniswap_x_integration_tests.rs b/tests/uniswap_x_integration_tests.rs index 5200578..8ea134f 100644 --- a/tests/uniswap_x_integration_tests.rs +++ b/tests/uniswap_x_integration_tests.rs @@ -89,7 +89,7 @@ fn test_sequential_swap_usx() { .clone(); let tycho_calldata = encode_tycho_router_call( - eth_chain().id, + eth_chain().id(), encoded_solution, &solution, &UserTransferType::TransferFrom,