diff --git a/config/router_addresses.json b/config/router_addresses.json new file mode 100644 index 0000000..bac76ba --- /dev/null +++ b/config/router_addresses.json @@ -0,0 +1,4 @@ +{ + "ethereum": "0x0178f471f219737c51d6005556d2f44de011a08a", + "base": "0xC2C23b0199525DE070D126860133dc3badaD2EEb" +} diff --git a/examples/encoding-example/main.rs b/examples/encoding-example/main.rs index 70b46d9..7ccc0bc 100644 --- a/examples/encoding-example/main.rs +++ b/examples/encoding-example/main.rs @@ -13,8 +13,6 @@ use tycho_execution::encoding::{ fn main() { // Setup variables - let router_address = Bytes::from_str("0x1234567890abcdef1234567890abcdef12345678") - .expect("Failed to create router address"); let swapper_pk = "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string(); let user_address = Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2") @@ -61,7 +59,6 @@ fn main() { exact_out: false, // it's an exact in solution checked_amount: None, // the amount out will not be checked in execution swaps: vec![simple_swap], - router_address, ..Default::default() }; diff --git a/src/encoding/evm/constants.rs b/src/encoding/evm/constants.rs index d742100..0b6eb48 100644 --- a/src/encoding/evm/constants.rs +++ b/src/encoding/evm/constants.rs @@ -1,6 +1,7 @@ use std::{collections::HashSet, sync::LazyLock}; pub const DEFAULT_EXECUTORS_JSON: &str = include_str!("../../../config/executor_addresses.json"); +pub const DEFAULT_ROUTERS_JSON: &str = include_str!("../../../config/router_addresses.json"); /// These protocols support the optimization of grouping swaps. /// diff --git a/src/encoding/evm/encoder_builder.rs b/src/encoding/evm/encoder_builder.rs index 7a13804..e20c148 100644 --- a/src/encoding/evm/encoder_builder.rs +++ b/src/encoding/evm/encoder_builder.rs @@ -1,4 +1,4 @@ -use tycho_common::models::Chain; +use tycho_common::{models::Chain, Bytes}; use crate::encoding::{ errors::EncodingError, @@ -17,6 +17,7 @@ pub struct EVMEncoderBuilder { strategy: Option>, chain: Option, executors_file_path: Option, + router_address: Option, } impl Default for EVMEncoderBuilder { @@ -27,7 +28,12 @@ impl Default for EVMEncoderBuilder { impl EVMEncoderBuilder { pub fn new() -> Self { - EVMEncoderBuilder { chain: None, strategy: None, executors_file_path: None } + EVMEncoderBuilder { + chain: None, + strategy: None, + executors_file_path: None, + router_address: None, + } } pub fn chain(mut self, chain: Chain) -> Self { self.chain = Some(chain); @@ -41,6 +47,13 @@ impl EVMEncoderBuilder { self } + /// Sets the `router_address` manually. + /// If it's not set, the default router address will be used (config/router_addresses.json) + pub fn router_address(mut self, router_address: Bytes) -> Self { + self.router_address = Some(router_address); + self + } + /// Sets the `strategy_encoder` manually. /// /// **Note**: This method should not be used in combination with `tycho_router` or @@ -56,12 +69,17 @@ impl EVMEncoderBuilder { if let Some(chain) = self.chain { let swap_encoder_registry = SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?; - let strategy = - Box::new(SplitSwapStrategyEncoder::new(chain, swap_encoder_registry, None)?); + let strategy = Box::new(SplitSwapStrategyEncoder::new( + chain, + swap_encoder_registry, + None, + self.router_address.clone(), + )?); Ok(EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy), executors_file_path: self.executors_file_path, + router_address: self.router_address, }) } else { Err(EncodingError::FatalError( @@ -83,11 +101,13 @@ impl EVMEncoderBuilder { chain, swap_encoder_registry, Some(swapper_pk), + self.router_address.clone(), )?); Ok(EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy), executors_file_path: self.executors_file_path, + router_address: self.router_address, }) } else { Err(EncodingError::FatalError( @@ -107,6 +127,7 @@ impl EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy), executors_file_path: self.executors_file_path, + router_address: self.router_address, }) } else { Err(EncodingError::FatalError( diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 7ac8fd7..e6ff1fd 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -1,4 +1,7 @@ -use std::{collections::HashSet, str::FromStr}; +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, +}; use alloy_primitives::{aliases::U24, U256, U8}; use alloy_sol_types::SolValue; @@ -8,6 +11,7 @@ use crate::encoding::{ errors::EncodingError, evm::{ approvals::permit2::Permit2, + constants::DEFAULT_ROUTERS_JSON, strategy_encoder::{group_swaps::group_swaps, strategy_validators::SplitSwapValidator}, swap_encoder::swap_encoder_registry::SwapEncoderRegistry, utils::{ @@ -68,6 +72,7 @@ pub trait EVMStrategyEncoder: StrategyEncoder { /// * `wrapped_address`: Address of the chain's wrapped token /// * `split_swap_validator`: SplitSwapValidator, responsible for checking validity of split swap /// solutions +/// * `router_address`: Address of the router to be used to execute swaps #[derive(Clone)] pub struct SplitSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, @@ -76,6 +81,7 @@ pub struct SplitSwapStrategyEncoder { native_address: Bytes, wrapped_address: Bytes, split_swap_validator: SplitSwapValidator, + router_address: Bytes, } impl SplitSwapStrategyEncoder { @@ -83,6 +89,7 @@ impl SplitSwapStrategyEncoder { blockchain: tycho_common::models::Chain, swap_encoder_registry: SwapEncoderRegistry, swapper_pk: Option, + router_address: Option, ) -> Result { let chain = Chain::from(blockchain); let (permit2, selector) = if let Some(swapper_pk) = swapper_pk { @@ -93,6 +100,21 @@ impl SplitSwapStrategyEncoder { "swap(uint256,address,address,uint256,bool,bool,uint256,address,bytes)".to_string(), ) }; + + let tycho_router_address; + if let Some(address) = router_address { + tycho_router_address = address; + } else { + let default_routers: HashMap = + serde_json::from_str(DEFAULT_ROUTERS_JSON)?; + tycho_router_address = default_routers + .get(&chain.name) + .ok_or(EncodingError::FatalError( + "No default router address found for chain".to_string(), + ))? + .to_owned(); + } + Ok(Self { permit2, selector, @@ -100,6 +122,7 @@ impl SplitSwapStrategyEncoder { native_address: chain.native_token()?, wrapped_address: chain.wrapped_token()?, split_swap_validator: SplitSwapValidator, + router_address: tycho_router_address, }) } } @@ -182,9 +205,9 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { let mut grouped_protocol_data: Vec = vec![]; for swap in grouped_swap.swaps.iter() { let encoding_context = EncodingContext { - receiver: solution.router_address.clone(), + receiver: self.router_address.clone(), exact_out: solution.exact_out, - router_address: solution.router_address.clone(), + router_address: Some(self.router_address.clone()), group_token_in: grouped_swap.input_token.clone(), group_token_out: grouped_swap.output_token.clone(), }; @@ -213,7 +236,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { }; let method_calldata = if let Some(permit2) = self.permit2.clone() { let (permit, signature) = permit2.get_permit( - &solution.router_address, + &self.router_address, &solution.sender, &solution.given_token, &solution.given_amount, @@ -248,7 +271,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { }; let contract_interaction = encode_input(&self.selector, method_calldata); - Ok((contract_interaction, solution.router_address)) + Ok((contract_interaction, self.router_address.clone())) } fn get_swap_encoder(&self, protocol_system: &str) -> Option<&Box> { @@ -293,7 +316,6 @@ impl StrategyEncoder for ExecutorStrategyEncoder { .ok_or_else(|| EncodingError::FatalError("Swap grouping failed".to_string()))?; let receiver = solution.receiver; - let router_address = solution.router_address; let swap_encoder = self .get_swap_encoder(&grouped_swap.protocol_system) @@ -309,7 +331,7 @@ impl StrategyEncoder for ExecutorStrategyEncoder { let encoding_context = EncodingContext { receiver: receiver.clone(), exact_out: solution.exact_out, - router_address: router_address.clone(), + router_address: None, group_token_in: grouped_swap.input_token.clone(), group_token_out: grouped_swap.output_token.clone(), }; @@ -396,7 +418,6 @@ mod tests { // The receiver was generated with `makeAddr("bob") using forge` receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(), swaps: vec![swap], - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), slippage: None, native_action: None, }; @@ -452,7 +473,6 @@ mod tests { sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(), receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(), swaps: vec![swap.clone(), swap], - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), slippage: None, native_action: None, }; @@ -521,7 +541,6 @@ mod tests { slippage: None, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap_usdc_eth, swap_eth_pepe], ..Default::default() }; @@ -606,9 +625,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: weth, @@ -619,7 +642,6 @@ mod tests { checked_amount, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap], ..Default::default() }; @@ -707,9 +729,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: eth(), @@ -719,7 +745,6 @@ mod tests { checked_amount: Some(BigUint::from_str("2659881924818443699787").unwrap()), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap], native_action: Some(NativeAction::Wrap), ..Default::default() @@ -756,9 +781,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: dai, @@ -768,7 +797,6 @@ mod tests { checked_amount: Some(BigUint::from_str("1_000000000000000000").unwrap()), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap], native_action: Some(NativeAction::Unwrap), ..Default::default() @@ -846,9 +874,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: weth, @@ -858,7 +890,6 @@ mod tests { checked_amount: Some(BigUint::from_str("26173932").unwrap()), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc], ..Default::default() }; @@ -927,9 +958,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: usdc, @@ -940,7 +975,6 @@ mod tests { slippage: None, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap_usdc_eth, swap_eth_pepe], ..Default::default() }; @@ -1043,8 +1077,13 @@ mod tests { }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, None).unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + None, + Some(Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap()), + ) + .unwrap(); let solution = Solution { exact_out: false, @@ -1057,7 +1096,6 @@ mod tests { // Alice sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap], ..Default::default() }; @@ -1094,8 +1132,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, None).unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + None, + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, given_token: weth, @@ -1106,7 +1149,6 @@ mod tests { checked_amount, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap], ..Default::default() }; @@ -1183,9 +1225,13 @@ mod tests { split: 0f64, }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, @@ -1197,7 +1243,6 @@ mod tests { slippage: None, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap_eth_pepe], ..Default::default() }; @@ -1247,9 +1292,13 @@ mod tests { }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, @@ -1261,7 +1310,6 @@ mod tests { slippage: None, sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), swaps: vec![swap_usdc_eth], ..Default::default() }; @@ -1331,9 +1379,13 @@ mod tests { }; let swap_encoder_registry = get_swap_encoder_registry(); - let encoder = - SplitSwapStrategyEncoder::new(eth_chain(), swap_encoder_registry, Some(private_key)) - .unwrap(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), + ) + .unwrap(); let solution = Solution { exact_out: false, @@ -1345,7 +1397,6 @@ mod tests { * test */ slippage: None, swaps: vec![swap_usdc_weth, swap_weth_usdc], - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), ..Default::default() @@ -1483,6 +1534,7 @@ mod tests { eth_chain(), swap_encoder_registry, Some(private_key.clone()), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), ) .unwrap(); @@ -1494,7 +1546,6 @@ mod tests { expected_amount: None, checked_amount: Some(BigUint::from_str("99574171").unwrap()), /* Expected output from * test */ - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), slippage: None, @@ -1640,6 +1691,7 @@ mod tests { eth_chain(), swap_encoder_registry, Some(private_key.clone()), + Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")), ) .unwrap(); @@ -1651,7 +1703,6 @@ mod tests { expected_amount: None, checked_amount: Some(BigUint::from_str("99525908").unwrap()), /* Expected output from * test */ - router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), slippage: None, diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index f119681..ad6ffc9 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -229,13 +229,19 @@ impl SwapEncoder for BalancerV2SwapEncoder { ) -> Result, EncodingError> { let token_approvals_manager = ProtocolApprovalsManager::new()?; let token = bytes_to_address(&swap.token_in)?; - let router_address = bytes_to_address(&encoding_context.router_address)?; - let approval_needed = token_approvals_manager.approval_needed( - token, - router_address, - Address::from_str(&self.vault_address) - .map_err(|_| EncodingError::FatalError("Invalid vault address".to_string()))?, - )?; + let approval_needed: bool; + + if let Some(router_address) = encoding_context.router_address { + let tycho_router_address = bytes_to_address(&router_address)?; + approval_needed = token_approvals_manager.approval_needed( + token, + tycho_router_address, + Address::from_str(&self.vault_address) + .map_err(|_| EncodingError::FatalError("Invalid vault address".to_string()))?, + )?; + } else { + approval_needed = true; + } let component_id = AlloyBytes::from_str(&swap.component.id) .map_err(|_| EncodingError::FatalError("Invalid component ID".to_string()))?; @@ -350,7 +356,7 @@ mod tests { let encoding_context = EncodingContext { receiver: Bytes::from("0x0000000000000000000000000000000000000001"), exact_out: false, - router_address: Bytes::zero(20), + router_address: Some(Bytes::zero(20)), group_token_in: token_in.clone(), group_token_out: token_out.clone(), }; @@ -397,7 +403,7 @@ mod tests { let encoding_context = EncodingContext { receiver: Bytes::from("0x0000000000000000000000000000000000000001"), exact_out: false, - router_address: Bytes::zero(20), + router_address: Some(Bytes::zero(20)), group_token_in: token_in.clone(), group_token_out: token_out.clone(), }; @@ -445,7 +451,7 @@ 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::zero(20)), group_token_in: token_in.clone(), group_token_out: token_out.clone(), }; @@ -503,7 +509,7 @@ mod tests { receiver: Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f"), exact_out: false, // Same as the executor address - router_address: Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f"), + router_address: Some(Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f")), group_token_in: token_in.clone(), group_token_out: token_out.clone(), @@ -567,7 +573,7 @@ mod tests { let encoding_context = EncodingContext { receiver: Bytes::from("0x0000000000000000000000000000000000000001"), exact_out: false, - router_address: Bytes::zero(20), + router_address: Some(Bytes::zero(20)), group_token_in: group_token_in.clone(), // Token out is the same as the group token out group_token_out: token_out.clone(), @@ -606,7 +612,7 @@ mod tests { let context = EncodingContext { receiver: receiver_address.clone(), exact_out: false, - router_address: router_address.clone(), + router_address: Some(router_address.clone()), group_token_in: usde_address.clone(), group_token_out: wbtc_address.clone(), }; @@ -734,7 +740,7 @@ mod tests { group_token_in: token_in.clone(), group_token_out: token_out.clone(), exact_out: false, - router_address: Bytes::default(), + router_address: Some(Bytes::default()), }; let encoder = EkuboSwapEncoder::new(String::default()); @@ -772,7 +778,7 @@ mod tests { group_token_in: group_token_in.clone(), group_token_out: group_token_out.clone(), exact_out: false, - router_address: Bytes::default(), + router_address: Some(Bytes::default()), }; let first_swap = Swap { diff --git a/src/encoding/evm/tycho_encoder.rs b/src/encoding/evm/tycho_encoder.rs index 5f20b2e..85f541f 100644 --- a/src/encoding/evm/tycho_encoder.rs +++ b/src/encoding/evm/tycho_encoder.rs @@ -249,7 +249,6 @@ mod tests { exact_out: false, given_amount: eth_amount_in.clone(), given_token: eth(), - router_address: Bytes::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap(), swaps: vec![swap], native_action: Some(NativeAction::Wrap), ..Default::default() diff --git a/src/encoding/models.rs b/src/encoding/models.rs index af8a780..a8fce6a 100644 --- a/src/encoding/models.rs +++ b/src/encoding/models.rs @@ -41,8 +41,6 @@ pub struct Solution { pub checked_amount: Option, /// List of swaps to fulfill the solution. pub swaps: Vec, - /// Address of the router contract to be used for the swaps. - pub router_address: Bytes, /// If set, the corresponding native action will be executed. pub native_action: Option, } @@ -104,14 +102,15 @@ pub struct Transaction { /// /// * `receiver`: Address of the receiver of the out token after the swaps are completed. /// * `exact_out`: true if the solution is a buy order, false if it is a sell order. -/// * `router_address`: Address of the router contract to be used for the swaps. +/// * `router_address`: Address of the router contract to be used for the swaps. Zero address if +/// solution does not require router address. /// * `group_token_in`: Token to be used as the input for the group swap. /// * `group_token_out`: Token to be used as the output for the group swap. #[derive(Clone, Debug)] pub struct EncodingContext { pub receiver: Bytes, pub exact_out: bool, - pub router_address: Bytes, + pub router_address: Option, pub group_token_in: Bytes, pub group_token_out: Bytes, }