diff --git a/src/encoding/strategy_encoder.rs b/src/encoding/strategy_encoder.rs index 735156d..c2eb5f8 100644 --- a/src/encoding/strategy_encoder.rs +++ b/src/encoding/strategy_encoder.rs @@ -1,3 +1,4 @@ +use alloy_primitives::Address; use alloy_sol_types::SolValue; use anyhow::Error; use num_bigint::BigUint; @@ -7,7 +8,7 @@ use std::cmp::min; use crate::encoding::models::{ ActionType, EncodingContext, NativeAction, Solution, PROPELLER_ROUTER_ADDRESS, }; -use crate::encoding::swap_encoder::{get_swap_encoder, get_swap_executor_address}; +use crate::encoding::swap_encoder::SWAP_ENCODER_REGISTRY; use crate::encoding::utils::{biguint_to_u256, ple_encode}; pub trait StrategyEncoder { @@ -19,13 +20,12 @@ pub trait StrategyEncoder { fn encode_protocol_header( &self, protocol_data: Vec, - protocol_system: String, + executor_address: Address, // Token indices, split, and token inclusion are only used for split swaps token_in: u16, token_out: u16, split: u16, // not sure what should be the type of this :/ ) -> Vec { - let executor_address = get_swap_executor_address(&protocol_system); let args = (executor_address, token_in, token_out, split, protocol_data); args.abi_encode() } @@ -77,8 +77,10 @@ impl StrategyEncoder for SequentialStrategyEncoder { let mut swaps = vec![]; for (index, swap) in solution.swaps.iter().enumerate() { let is_last = index == solution.swaps.len() - 1; - let protocol_system = swap.component.protocol_system.clone(); - let swap_encoder = get_swap_encoder(&protocol_system); + let registry = SWAP_ENCODER_REGISTRY.read().unwrap(); + let swap_encoder = registry + .get_encoder(&swap.component.protocol_system) + .expect("Swap encoder not found"); let router_address = if solution.router_address.is_some() { solution.router_address.clone().unwrap() } else { @@ -96,7 +98,8 @@ impl StrategyEncoder for SequentialStrategyEncoder { address_for_approvals: router_address, }; let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context)?; - let swap_data = self.encode_protocol_header(protocol_data, protocol_system, 0, 0, 0); + let executor_address = swap_encoder.executor_address(); + let swap_data = self.encode_protocol_header(protocol_data, executor_address, 0, 0, 0); swaps.push(swap_data); } @@ -165,8 +168,10 @@ impl StrategyEncoder for StraightToPoolStrategyEncoder { )); } let swap = solution.swaps.first().unwrap(); - let protocol_system = swap.component.protocol_system.clone(); - let swap_encoder = get_swap_encoder(&protocol_system); + let registry = SWAP_ENCODER_REGISTRY.read().unwrap(); + let swap_encoder = registry + .get_encoder(&swap.component.protocol_system) + .expect("Swap encoder not found"); let router_address = solution.router_address.unwrap(); let encoding_context = EncodingContext { @@ -175,6 +180,7 @@ impl StrategyEncoder for StraightToPoolStrategyEncoder { address_for_approvals: router_address, }; let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context)?; + // TODO: here we need to pass also the address of the executor to be used Ok(protocol_data) } diff --git a/src/encoding/swap_encoder/builder.rs b/src/encoding/swap_encoder/builder.rs new file mode 100644 index 0000000..9a8768d --- /dev/null +++ b/src/encoding/swap_encoder/builder.rs @@ -0,0 +1,39 @@ +use crate::encoding::swap_encoder::swap_encoder::{ + BalancerV2SwapEncoder, SwapEncoder, UniswapV2SwapEncoder, +}; +use alloy_primitives::Address; +use std::str::FromStr; + +pub struct SwapEncoderBuilder { + protocol_system: String, + executor_address: Option
, +} + +impl SwapEncoderBuilder { + pub fn new(protocol_system: &str) -> Self { + SwapEncoderBuilder { + protocol_system: protocol_system.to_string(), + executor_address: None, + } + } + + pub fn executor_address(mut self, address: &str) -> Self { + self.executor_address = + Some(Address::from_str(address).expect(&format!("Invalid address: {}", address))); + self + } + + pub fn build(self) -> Result, String> { + let executor_address = self.executor_address.ok_or_else(|| { + format!( + "Executor address must be provided for protocol: {}", + self.protocol_system + ) + })?; + match self.protocol_system.as_str() { + "uniswap_v2" => Ok(Box::new(UniswapV2SwapEncoder::new(executor_address))), + "vm:balancer_v2" => Ok(Box::new(BalancerV2SwapEncoder::new(executor_address))), + _ => Err(format!("Unknown protocol system: {}", self.protocol_system)), + } + } +} diff --git a/src/encoding/swap_encoder/config.json b/src/encoding/swap_encoder/config.json new file mode 100644 index 0000000..11bc16e --- /dev/null +++ b/src/encoding/swap_encoder/config.json @@ -0,0 +1,6 @@ +{ + "executors": { + "uniswap_v2": "0x5C2F5a71f67c01775180ADc06909288B4C329308", + "vm:balancer_v2": "0x543778987b293C7E8Cf0722BB2e935ba6f4068D4" + } +} \ No newline at end of file diff --git a/src/encoding/swap_encoder/mod.rs b/src/encoding/swap_encoder/mod.rs new file mode 100644 index 0000000..85f6b2f --- /dev/null +++ b/src/encoding/swap_encoder/mod.rs @@ -0,0 +1,14 @@ +use crate::encoding::swap_encoder::registry::{Config, SwapEncoderRegistry}; +use lazy_static::lazy_static; +use std::sync::RwLock; + +mod builder; +mod registry; +mod swap_encoder; + +lazy_static! { + pub static ref SWAP_ENCODER_REGISTRY: RwLock = { + let config = Config::from_file("config.json").expect("Failed to load configuration file"); + RwLock::new(SwapEncoderRegistry::new(config)) + }; +} diff --git a/src/encoding/swap_encoder/registry.rs b/src/encoding/swap_encoder/registry.rs new file mode 100644 index 0000000..cd57d0e --- /dev/null +++ b/src/encoding/swap_encoder/registry.rs @@ -0,0 +1,43 @@ +use crate::encoding::swap_encoder::builder::SwapEncoderBuilder; +use crate::encoding::swap_encoder::swap_encoder::SwapEncoder; +use serde::Deserialize; +use std::collections::HashMap; +use std::fs; + +pub struct SwapEncoderRegistry { + encoders: HashMap>, +} + +impl SwapEncoderRegistry { + pub fn new(config: Config) -> Self { + let mut encoders = HashMap::new(); + + for (protocol, executor_address) in config.executors { + let builder = SwapEncoderBuilder::new(&protocol).executor_address(&executor_address); + let encoder = builder.build().expect(&format!( + "Failed to build swap encoder for protocol: {}", + protocol + )); + encoders.insert(protocol, encoder); + } + + Self { encoders } + } + + pub fn get_encoder(&self, protocol_system: &str) -> Option<&Box> { + self.encoders.get(protocol_system) + } +} + +#[derive(Deserialize)] +pub struct Config { + pub executors: HashMap, // Protocol -> Executor address mapping +} + +impl Config { + pub fn from_file(path: &str) -> Result { + let config_str = fs::read_to_string(path)?; + let config: Config = serde_json::from_str(&config_str)?; + Ok(config) + } +} diff --git a/src/encoding/swap_encoder.rs b/src/encoding/swap_encoder/swap_encoder.rs similarity index 71% rename from src/encoding/swap_encoder.rs rename to src/encoding/swap_encoder/swap_encoder.rs index c3181fe..310a95d 100644 --- a/src/encoding/swap_encoder.rs +++ b/src/encoding/swap_encoder/swap_encoder.rs @@ -8,23 +8,37 @@ use std::str::FromStr; pub trait SwapEncoder: Sync + Send { fn encode_swap(&self, swap: Swap, encoding_context: EncodingContext) -> Result, Error>; + fn executor_address(&self) -> Address; } -struct UniswapV2SwapEncoder {} +pub struct UniswapV2SwapEncoder { + executor_address: Address, +} +impl UniswapV2SwapEncoder { + pub fn new(executor_address: Address) -> Self { + Self { executor_address } + } +} impl SwapEncoder for UniswapV2SwapEncoder { fn encode_swap(&self, swap: Swap, encoding_context: EncodingContext) -> Result, Error> { todo!() } + + fn executor_address(&self) -> Address { + self.executor_address + } } -struct BalancerV2SwapEncoder { +pub struct BalancerV2SwapEncoder { + executor_address: Address, vault_address: Address, } impl BalancerV2SwapEncoder { - pub fn new() -> Self { + pub fn new(executor_address: Address) -> Self { Self { + executor_address, vault_address: Address::from_str("0xba12222222228d8ba445958a75a0704d566bf2c8") .expect("Invalid string for balancer vault address"), } @@ -57,22 +71,8 @@ impl SwapEncoder for BalancerV2SwapEncoder { ); Ok(args.abi_encode()) } -} -pub fn get_swap_encoder(protocol_system: &str) -> Box { - match protocol_system { - "uniswap_v2" => Box::new(UniswapV2SwapEncoder {}), - "vm:balancer_v2" => Box::new(BalancerV2SwapEncoder::new()), - _ => panic!("Unknown protocol system: {}", protocol_system), - } -} - -pub fn get_swap_executor_address(protocol_system: &str) -> Address { - match protocol_system { - "uniswap_v2" => Address::from_str("0x5C2F5a71f67c01775180ADc06909288B4C329308") - .expect("Invalid address"), - "vm:balancer_v2" => Address::from_str("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4") - .expect("Invalid address"), - _ => panic!("Unknown protocol system: {}", protocol_system), + fn executor_address(&self) -> Address { + self.executor_address } }