Merge branch 'refs/heads/main' into hooks/dc/ENG-4624-pass-hook-data

# Conflicts:
#	foundry/test/assets/calldata.txt

Took 9 minutes
This commit is contained in:
Diana Carvalho
2025-07-31 17:50:45 +01:00
53 changed files with 5302 additions and 643 deletions

View File

@@ -4,10 +4,9 @@ pub mod encoding;
use std::str::FromStr;
use alloy::{primitives::B256, signers::local::PrivateKeySigner};
use tycho_common::{models::Chain as TychoCommonChain, Bytes};
use tycho_common::{models::Chain, Bytes};
use tycho_execution::encoding::{
evm::encoder_builders::TychoRouterEncoderBuilder,
models::{Chain, UserTransferType},
evm::encoder_builders::TychoRouterEncoderBuilder, models::UserTransferType,
tycho_encoder::TychoEncoder,
};
@@ -16,7 +15,7 @@ pub fn router_address() -> Bytes {
}
pub fn eth_chain() -> Chain {
TychoCommonChain::Ethereum.into()
Chain::Ethereum
}
pub fn eth() -> Bytes {
@@ -43,6 +42,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 =

View File

@@ -48,6 +48,7 @@ fn test_uniswap_v3_uniswap_v2() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
component: ProtocolComponent {
@@ -59,6 +60,7 @@ fn test_uniswap_v3_uniswap_v2() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -80,7 +82,7 @@ fn test_uniswap_v3_uniswap_v2() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -127,6 +129,7 @@ fn test_uniswap_v3_uniswap_v3() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
component: ProtocolComponent {
@@ -146,6 +149,7 @@ fn test_uniswap_v3_uniswap_v3() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -167,7 +171,7 @@ fn test_uniswap_v3_uniswap_v3() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -213,6 +217,7 @@ fn test_uniswap_v3_curve() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdt = Swap {
@@ -242,6 +247,7 @@ fn test_uniswap_v3_curve() {
token_out: usdt.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -263,7 +269,7 @@ fn test_uniswap_v3_curve() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -301,6 +307,7 @@ fn test_balancer_v2_uniswap_v2() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
@@ -313,6 +320,7 @@ fn test_balancer_v2_uniswap_v2() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -334,7 +342,7 @@ fn test_balancer_v2_uniswap_v2() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -375,6 +383,7 @@ fn test_multi_protocol() {
token_out: weth.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let balancer_swap_weth_wbtc = Swap {
@@ -387,6 +396,7 @@ fn test_multi_protocol() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let curve_swap_wbtc_usdt = Swap {
@@ -416,6 +426,7 @@ fn test_multi_protocol() {
token_out: usdt.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
// Ekubo
@@ -438,6 +449,7 @@ fn test_multi_protocol() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
// USV4
@@ -461,6 +473,7 @@ fn test_multi_protocol() {
token_out: eth.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -490,7 +503,7 @@ fn test_multi_protocol() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -533,6 +546,7 @@ fn test_uniswap_v3_balancer_v3() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_qnt = Swap {
component: ProtocolComponent {
@@ -544,6 +558,7 @@ fn test_uniswap_v3_balancer_v3() {
token_out: qnt.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -565,7 +580,7 @@ fn test_uniswap_v3_balancer_v3() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,

View File

@@ -40,6 +40,7 @@ fn test_single_encoding_strategy_ekubo() {
token_out: token_out.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -63,7 +64,7 @@ fn test_single_encoding_strategy_ekubo() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -92,6 +93,7 @@ fn test_single_encoding_strategy_maverick() {
token_out: token_out.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -115,7 +117,7 @@ fn test_single_encoding_strategy_maverick() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -156,6 +158,7 @@ fn test_single_encoding_strategy_usv4_eth_in() {
token_out: pepe.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -177,7 +180,7 @@ fn test_single_encoding_strategy_usv4_eth_in() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -222,6 +225,7 @@ fn test_single_encoding_strategy_usv4_eth_out() {
token_out: eth.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -244,7 +248,7 @@ fn test_single_encoding_strategy_usv4_eth_out() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -296,6 +300,7 @@ fn test_single_encoding_strategy_usv4_grouped_swap() {
token_out: eth.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_eth_pepe = Swap {
@@ -309,6 +314,7 @@ fn test_single_encoding_strategy_usv4_grouped_swap() {
token_out: pepe.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -330,7 +336,7 @@ fn test_single_encoding_strategy_usv4_grouped_swap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -420,6 +426,7 @@ fn test_single_encoding_strategy_curve() {
token_out: token_out.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -443,7 +450,7 @@ fn test_single_encoding_strategy_curve() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -487,6 +494,7 @@ fn test_single_encoding_strategy_curve_st_eth() {
token_out: token_out.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -510,7 +518,7 @@ fn test_single_encoding_strategy_curve_st_eth() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -540,6 +548,7 @@ fn test_single_encoding_strategy_balancer_v3() {
token_out: token_out.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -563,7 +572,7 @@ fn test_single_encoding_strategy_balancer_v3() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,

View File

@@ -37,6 +37,7 @@ fn test_sequential_swap_strategy_encoder() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
component: ProtocolComponent {
@@ -48,6 +49,7 @@ fn test_sequential_swap_strategy_encoder() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -69,7 +71,7 @@ fn test_sequential_swap_strategy_encoder() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -103,6 +105,7 @@ fn test_sequential_swap_strategy_encoder_no_permit2() {
token_out: wbtc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
component: ProtocolComponent {
@@ -114,6 +117,7 @@ fn test_sequential_swap_strategy_encoder_no_permit2() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -135,7 +139,7 @@ fn test_sequential_swap_strategy_encoder_no_permit2() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -215,6 +219,7 @@ fn test_sequential_strategy_cyclic_swap() {
token_out: weth.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
// WETH -> USDC (Pool 2)
@@ -237,6 +242,7 @@ fn test_sequential_strategy_cyclic_swap() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -260,7 +266,7 @@ fn test_sequential_strategy_cyclic_swap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,

View File

@@ -33,6 +33,7 @@ fn test_single_swap_strategy_encoder() {
token_out: dai.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -54,7 +55,7 @@ fn test_single_swap_strategy_encoder() {
.unwrap();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solutions[0].clone(),
&solution,
&UserTransferType::TransferFromPermit2,
@@ -119,6 +120,7 @@ fn test_single_swap_strategy_encoder_no_permit2() {
token_out: dai.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
@@ -139,7 +141,7 @@ fn test_single_swap_strategy_encoder_no_permit2() {
.unwrap()[0]
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFrom,
@@ -201,6 +203,7 @@ fn test_single_swap_strategy_encoder_no_transfer_in() {
token_out: dai.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::None);
@@ -221,7 +224,7 @@ fn test_single_swap_strategy_encoder_no_transfer_in() {
.unwrap()[0]
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::None,
@@ -284,6 +287,7 @@ fn test_single_swap_strategy_encoder_wrap() {
token_out: dai.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -305,7 +309,7 @@ fn test_single_swap_strategy_encoder_wrap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -336,6 +340,7 @@ fn test_single_swap_strategy_encoder_unwrap() {
token_out: weth(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -357,7 +362,7 @@ fn test_single_swap_strategy_encoder_unwrap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,

View File

@@ -42,6 +42,7 @@ fn test_split_swap_strategy_encoder() {
token_out: dai.clone(),
split: 0.5f64,
user_data: None,
protocol_state: None,
};
let swap_weth_wbtc = Swap {
component: ProtocolComponent {
@@ -56,6 +57,7 @@ fn test_split_swap_strategy_encoder() {
// It should still be very close to 50%
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_dai_usdc = Swap {
component: ProtocolComponent {
@@ -67,6 +69,7 @@ fn test_split_swap_strategy_encoder() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_wbtc_usdc = Swap {
component: ProtocolComponent {
@@ -78,6 +81,7 @@ fn test_split_swap_strategy_encoder() {
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -99,7 +103,7 @@ fn test_split_swap_strategy_encoder() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -144,6 +148,7 @@ fn test_split_input_cyclic_swap() {
token_out: weth.clone(),
split: 0.6f64, // 60% of input
user_data: None,
protocol_state: None,
};
// USDC -> WETH (Pool 2) - 40% of input (remaining)
@@ -166,6 +171,7 @@ fn test_split_input_cyclic_swap() {
token_out: weth.clone(),
split: 0f64,
user_data: None, // Remaining 40%
protocol_state: None,
};
// WETH -> USDC (Pool 2)
@@ -188,6 +194,7 @@ fn test_split_input_cyclic_swap() {
token_out: usdc.clone(),
split: 0.0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -212,7 +219,7 @@ fn test_split_input_cyclic_swap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,
@@ -308,6 +315,7 @@ fn test_split_output_cyclic_swap() {
token_out: weth.clone(),
split: 0.0f64,
user_data: None,
protocol_state: None,
};
let swap_weth_usdc_v3_pool1 = Swap {
@@ -327,6 +335,7 @@ fn test_split_output_cyclic_swap() {
token_out: usdc.clone(),
split: 0.6f64,
user_data: None,
protocol_state: None,
};
let swap_weth_usdc_v3_pool2 = Swap {
@@ -348,6 +357,7 @@ fn test_split_output_cyclic_swap() {
token_out: usdc.clone(),
split: 0.0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFromPermit2);
@@ -372,7 +382,7 @@ fn test_split_output_cyclic_swap() {
.clone();
let calldata = encode_tycho_router_call(
eth_chain().id,
eth_chain().id(),
encoded_solution,
&solution,
&UserTransferType::TransferFromPermit2,

View File

@@ -0,0 +1,125 @@
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::{
dai, encoding::encode_tycho_router_call, eth, eth_chain, get_tycho_router_encoder,
router_address, usdc, usdt,
};
mod common;
#[test]
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 pools
//
// DAI ───(USV3)──> USDC ───(USV2)──> USDT
// 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 dai = dai();
let usdc = usdc();
let usdt = usdt();
let swap_dai_usdc = Swap {
component: ProtocolComponent {
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(100).to_signed_bytes_be()));
attrs
},
..Default::default()
},
token_in: dai.clone(),
token_out: usdc.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let swap_usdc_usdt = Swap {
component: ProtocolComponent {
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(),
token_out: usdt.clone(),
split: 0f64,
user_data: None,
protocol_state: None,
};
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
let solution = Solution {
exact_out: false,
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_dai_usdc, swap_usdc_usdt],
..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,
&eth(),
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(&dai).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, 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_usx", hex_calldata.as_str());
}