From 647f697ea2759610674defb4b1fffb2481b09a5f Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 14 Jan 2025 10:37:06 +0000 Subject: [PATCH] chore: Refactor models: - Delete min_checked_amount and use check_amount instead - Use Bytes and not Address in interfaces - Move router_address from Solution to Order --- src/encoding/approvals_manager.rs | 4 +-- src/encoding/models.rs | 41 +++++++++++++---------- src/encoding/permit2.rs | 12 +++---- src/encoding/router_encoder.rs | 31 ++++-------------- src/encoding/strategy_encoder.rs | 54 ++++++++++++++----------------- src/encoding/swap_encoder.rs | 13 ++++---- 6 files changed, 69 insertions(+), 86 deletions(-) diff --git a/src/encoding/approvals_manager.rs b/src/encoding/approvals_manager.rs index fb37bfb..3747557 100644 --- a/src/encoding/approvals_manager.rs +++ b/src/encoding/approvals_manager.rs @@ -20,8 +20,8 @@ impl TokenApprovalsManager { pub async fn approval_needed( &self, token: Bytes, - spender_address: Address, - router_address: Address, + spender_address: Bytes, + router_address: Bytes, ) -> bool { // should be something like // let allowance = self diff --git a/src/encoding/models.rs b/src/encoding/models.rs index bb35846..d820000 100644 --- a/src/encoding/models.rs +++ b/src/encoding/models.rs @@ -1,17 +1,18 @@ -use alloy_primitives::Address; +use lazy_static::lazy_static; use num_bigint::BigUint; +use std::env; +use std::str::FromStr; use tycho_core::{dto::ProtocolComponent, Bytes}; +lazy_static! { + pub static ref PROPELLER_ROUTER_ADDRESS: Bytes = Bytes::from_str( + &env::var("ROUTER_ADDRESS").expect("Missing ROUTER_ADDRESS in environment"), + ) + .expect("Invalid ROUTER_ADDRESS"); +} + pub struct Solution { pub orders: Vec, - // if not set, then the Propeller Router will be used - pub router_address: Option
, -} - -#[derive(Clone)] -pub enum NativeAction { - Wrap, - Unwrap, } pub struct Order { @@ -24,7 +25,7 @@ pub struct Order { /// The token being bought (exact in) or sold (exact out). checked_token: Bytes, /// Amount of the checked token. - checked_amount: BigUint, + pub check_amount: BigUint, /// Address of the sender. pub sender: Bytes, /// Address of the receiver. @@ -33,12 +34,20 @@ pub struct Order { pub swaps: Vec, /// Whether to include router calldata (true) or just swap data (false). add_router_calldata: bool, - - pub slippage: f64, - pub min_checked_amount: Option, + // if not set, then the Propeller Router will be used + pub router_address: Option, + // if set, it will be applied to check_amount + pub slippage: Option, + // if set, the corresponding native action will be executed pub native_action: Option, } +#[derive(Clone)] +pub enum NativeAction { + Wrap, + Unwrap, +} + #[derive(Clone)] pub struct Swap { /// Protocol component from tycho indexer @@ -51,12 +60,10 @@ pub struct Swap { pub split: f64, } -// maybe this struct is useful - keeping it here for now (maybe we could collapse this with another -// struct) pub struct EncodingContext { - pub receiver: Address, + pub receiver: Bytes, pub exact_out: bool, - pub router_address: Address, + pub router_address: Bytes, } pub enum ActionType { diff --git a/src/encoding/permit2.rs b/src/encoding/permit2.rs index d76ba27..3a68bbf 100644 --- a/src/encoding/permit2.rs +++ b/src/encoding/permit2.rs @@ -7,17 +7,17 @@ pub struct PermitRequest { pub token: Bytes, pub amount: BigUint, pub spender: Bytes, - pub router_address: Address, + pub router_address: Bytes, } pub struct Permit2 { - pub address: Address, + pub address: Bytes, } impl Permit2 { pub fn new() -> Self { Self { - address: Address::from_str("0x000000000022D473030F116dDEE9F6B43aC78BA3") + address: Bytes::from_str("0x000000000022D473030F116dDEE9F6B43aC78BA3") .expect("Permit2 address not valid"), } } @@ -33,9 +33,9 @@ impl Permit2 { fn get_allowance_data( &self, - user: Address, - router_address: Address, - token: Address, + user: Bytes, + router_address: Bytes, + token: Bytes, ) -> (U256, u64, U256) { // get allowance data (if it exists) and the nonce // returns permitAmount, expiration, nonce diff --git a/src/encoding/router_encoder.rs b/src/encoding/router_encoder.rs index abdcbf8..ec9912d 100644 --- a/src/encoding/router_encoder.rs +++ b/src/encoding/router_encoder.rs @@ -1,44 +1,24 @@ -use crate::encoding::models::{Order, Solution}; +use crate::encoding::models::{Order, Solution, PROPELLER_ROUTER_ADDRESS}; use crate::encoding::permit2::{Permit2, PermitRequest}; use crate::encoding::strategy_encoder::{ SequentialExactInStrategyEncoder, SingleSwapStrategyEncoder, SlipSwapStrategyEncoder, StrategyEncoder, }; use crate::encoding::utils::{encode_input, ple_encode}; -use alloy_primitives::Address; use alloy_sol_types::SolValue; use anyhow::Error; -use std::env; use std::str::FromStr; -struct RouterEncoder { - router_address: Address, -} +struct RouterEncoder {} impl RouterEncoder { - pub fn new() -> Self { - let router_address = Address::from_str( - &env::var("ROUTER_ADDRESS").expect("Missing ROUTER_ADDRESS in environment"), - ) - .expect("Invalid ROUTER_ADDRESS"); - Self { router_address } - } - pub fn encode_router_calldata(&self, solution: Solution) -> Result, Error> { let permit_calldata = self.handle_approvals(&solution)?; // TODO: where should we append this? let mut calldata_list: Vec> = Vec::new(); let encode_for_batch_execute = solution.orders.len() > 1; for order in solution.orders { let strategy = self.get_strategy(&order); - let contract_interaction = strategy.encode_strategy( - order, - if solution.router_address.is_some() { - solution.router_address.unwrap() - } else { - self.router_address - }, - encode_for_batch_execute, - )?; + let contract_interaction = strategy.encode_strategy(order, encode_for_batch_execute)?; calldata_list.push(contract_interaction); } if encode_for_batch_execute { @@ -56,7 +36,10 @@ impl RouterEncoder { token: order.given_token.clone(), spender: order.sender.clone(), amount: order.given_amount.clone(), - router_address: solution.router_address.unwrap_or(self.router_address), + router_address: order + .router_address + .clone() + .unwrap_or(PROPELLER_ROUTER_ADDRESS.clone()), }); } Ok(Permit2::new().encode_permit(permits)) diff --git a/src/encoding/strategy_encoder.rs b/src/encoding/strategy_encoder.rs index a33f23b..63593ad 100644 --- a/src/encoding/strategy_encoder.rs +++ b/src/encoding/strategy_encoder.rs @@ -4,7 +4,9 @@ use anyhow::Error; use num_bigint::BigUint; use std::cmp::min; -use crate::encoding::models::{ActionType, EncodingContext, NativeAction, Order}; +use crate::encoding::models::{ + ActionType, EncodingContext, NativeAction, Order, PROPELLER_ROUTER_ADDRESS, +}; use crate::encoding::swap_encoder::{get_swap_encoder, get_swap_executor_address}; use crate::encoding::utils::{biguint_to_u256, bytes_to_address, encode_input, ple_encode}; @@ -12,7 +14,6 @@ pub trait StrategyEncoder { fn encode_strategy( &self, to_encode: Order, - router_address: Address, encode_for_batch_execute: bool, ) -> Result, Error>; @@ -37,7 +38,6 @@ impl StrategyEncoder for SingleSwapStrategyEncoder { fn encode_strategy( &self, order: Order, - router_address: Address, encode_for_batch_execute: bool, ) -> Result, Error> { todo!() @@ -50,29 +50,31 @@ impl StrategyEncoder for SequentialExactInStrategyEncoder { fn encode_strategy( &self, order: Order, - router_address: Address, encode_for_batch_execute: bool, ) -> Result, Error> { - let one_hundred = BigUint::from(100u32); - let slippage_percent = BigUint::from((order.slippage * 100.0) as u32); - let multiplier = &one_hundred - slippage_percent; - let slippage_buy_amount = (&order.given_amount * multiplier) / one_hundred; - - let min_checked_amount = if order.min_checked_amount.is_some() { - min(order.min_checked_amount.unwrap(), slippage_buy_amount) - } else { - slippage_buy_amount - }; + let mut check_amount = order.check_amount.clone(); + if order.slippage.is_some() { + let one_hundred = BigUint::from(100u32); + let slippage_percent = BigUint::from((order.slippage.unwrap() * 100.0) as u32); + let multiplier = &one_hundred - slippage_percent; + check_amount = (&order.check_amount * multiplier) / one_hundred; + } let mut swaps = vec![]; for (index, swap) in order.swaps.iter().enumerate() { let is_last = index == order.swaps.len() - 1; let protocol_system = swap.component.protocol_system.clone(); let swap_encoder = get_swap_encoder(&protocol_system); - let receiver = if is_last { - bytes_to_address(&order.receiver)? + let router_address = if order.router_address.is_some() { + order.router_address.clone().unwrap() } else { - router_address + PROPELLER_ROUTER_ADDRESS.clone() }; + let receiver = if is_last { + order.receiver.clone() + } else { + router_address.clone() + }; + let encoding_context = EncodingContext { receiver, exact_out: order.exact_out, @@ -82,17 +84,10 @@ impl StrategyEncoder for SequentialExactInStrategyEncoder { let swap_data = self.encode_protocol_header(protocol_data, protocol_system, 0, 0, 0); swaps.push(swap_data); } - let (selector, action_type) = if order.exact_out { - ( - "sequentialExactOut(uint256, uint256, bytes[])", - ActionType::SequentialExactOut, - ) - } else { - ( - "sequentialExactIn(uint256, uint256, bytes[])", - ActionType::SequentialExactIn, - ) - }; + + let selector = "sequentialExactIn(uint256, uint256, bytes[])"; + let action_type = ActionType::SequentialExactIn; + let encoded_swaps = ple_encode(swaps); let (mut unwrap, mut wrap) = (false, false); @@ -106,7 +101,7 @@ impl StrategyEncoder for SequentialExactInStrategyEncoder { wrap, unwrap, biguint_to_u256(&order.given_amount), - biguint_to_u256(&min_checked_amount), + biguint_to_u256(&check_amount), encoded_swaps, ) .abi_encode(); @@ -125,7 +120,6 @@ impl StrategyEncoder for SlipSwapStrategyEncoder { fn encode_strategy( &self, order: Order, - router_address: Address, encode_for_batch_execute: bool, ) -> Result, Error> { todo!() diff --git a/src/encoding/swap_encoder.rs b/src/encoding/swap_encoder.rs index 0c025d5..5227f5e 100644 --- a/src/encoding/swap_encoder.rs +++ b/src/encoding/swap_encoder.rs @@ -2,6 +2,7 @@ use alloy_primitives::Address; use alloy_sol_types::SolValue; use anyhow::Error; use std::str::FromStr; +use tycho_core::Bytes; use crate::encoding::utils::bytes_to_address; use crate::encoding::{ @@ -22,16 +23,14 @@ impl SwapEncoder for UniswapV2SwapEncoder { } struct BalancerV2SwapEncoder { - vault_address: Option
, + vault_address: Bytes, } impl BalancerV2SwapEncoder { pub fn new() -> Self { Self { - vault_address: Some( - Address::from_str("0xba12222222228d8ba445958a75a0704d566bf2c8") - .expect("Invalid string for balancer vault address"), - ), + vault_address: Bytes::from_str("0xba12222222228d8ba445958a75a0704d566bf2c8") + .expect("Invalid string for balancer vault address"), } } } @@ -49,7 +48,7 @@ impl SwapEncoder for BalancerV2SwapEncoder { .approval_needed( swap.token_in.clone(), encoding_context.router_address, - self.vault_address.unwrap(), + self.vault_address.clone(), ) .await }); @@ -59,7 +58,7 @@ impl SwapEncoder for BalancerV2SwapEncoder { bytes_to_address(&swap.token_in)?, bytes_to_address(&swap.token_out)?, swap.component.id, - encoding_context.receiver, + bytes_to_address(&encoding_context.receiver)?, encoding_context.exact_out, approval_needed, );