kabu_execution_multicaller/
swap_encoder.rs

1use crate::MulticallerSwapEncoder;
2use alloy_primitives::{Address, BlockNumber, Bytes, U256};
3use eyre::{eyre, OptionExt, Result};
4use kabu_types_blockchain::MulticallerCalls;
5use kabu_types_entities::tips::{tips_and_value_for_swap_type, Tips};
6use kabu_types_entities::{Swap, SwapEncoder, SwapStep};
7use tracing::{debug, error, trace};
8
9impl SwapEncoder for MulticallerSwapEncoder {
10    fn set_address(&mut self, multicaller_address: Address) {
11        self.multicaller_address = multicaller_address;
12        self.swap_step_encoder.multicaller_address = multicaller_address;
13        self.swap_step_encoder.swap_line_encoder.multicaller_address = multicaller_address;
14    }
15
16    fn address(&self) -> Address {
17        self.multicaller_address
18    }
19
20    fn encode(
21        &self,
22        swap: Swap,
23        tips_pct: Option<u32>,
24        _next_block_number: Option<BlockNumber>,
25        gas_cost: Option<U256>,
26        sender_address: Option<Address>,
27        sender_eth_balance: Option<U256>,
28    ) -> Result<(Address, Option<U256>, Bytes, Vec<Tips>)> {
29        let swap_vec = match &swap {
30            Swap::BackrunSwapLine(_) | Swap::BackrunSwapSteps(_) => {
31                vec![swap.to_swap_steps(self.swap_step_encoder.get_contract_address()).ok_or_eyre("SWAP_TYPE_NOTE_COVERED")?]
32            }
33            Swap::Multiple(swap_vec) => {
34                let mut ret: Vec<(SwapStep, SwapStep)> = Vec::new();
35                for s in swap_vec.iter() {
36                    ret.push(s.to_swap_steps(self.swap_step_encoder.get_contract_address()).ok_or_eyre("AA")?);
37                }
38                ret
39            }
40            Swap::ExchangeSwapLine(_) => vec![],
41            Swap::None => {
42                vec![]
43            }
44        };
45
46        let mut swap_steps = "".to_string();
47        for (level, (sp0, sp1)) in swap_vec.iter().enumerate() {
48            swap_steps.push_str(format!("{}{} \n{}\t-> {}\n", "\t".repeat(level), sp0, "\t".repeat(level), sp1).as_str());
49        }
50        debug!("Swaps:\n{}", swap_steps);
51
52        let mut swap_opcodes = if swap_vec.is_empty() {
53            match &swap {
54                Swap::ExchangeSwapLine(swap_line) => {
55                    trace!("START: exchange swap line");
56                    match self.swap_step_encoder.swap_line_encoder.encode_swap_line_in_amount(swap_line, None) {
57                        Ok(calls) => calls,
58                        Err(e) => {
59                            error!("swap_line_encoder.encode_swap_line_in_amount : {}", e);
60                            return Err(eyre!("ENCODING_FAILED"));
61                        }
62                    }
63                }
64                _ => return Err(eyre!("NO_SWAP_STEPS")),
65            }
66        } else if swap_vec.len() == 1 {
67            trace!("START: encode_swap_steps two-hop");
68            let sp0 = &swap_vec[0].0;
69            let sp1 = &swap_vec[0].1;
70            self.swap_step_encoder.encode_swap_steps(sp0, sp1)?
71        } else {
72            trace!("START: encode_swap_steps multi-hop");
73            let mut ret = MulticallerCalls::new();
74            for (sp0, sp1) in swap_vec.iter() {
75                ret = self.swap_step_encoder.encode_do_calls(ret, self.swap_step_encoder.encode_swap_steps(sp0, sp1)?)?;
76            }
77            ret
78        };
79        trace!("END: swap_opcodes");
80
81        let tips_vec =
82            if let (Some(tips_pct), Some(sender_address), Some(sender_eth_balance)) = (tips_pct, sender_address, sender_eth_balance) {
83                let (tips_vec, _call_value) = tips_and_value_for_swap_type(&swap, Some(tips_pct), gas_cost, sender_eth_balance)?;
84                for tips in &tips_vec {
85                    swap_opcodes = self.swap_step_encoder.encode_tips(
86                        swap_opcodes,
87                        tips.token_in.get_address(),
88                        tips.min_change,
89                        tips.tips,
90                        sender_address,
91                    )?;
92                }
93                tips_vec
94            } else {
95                vec![]
96            };
97
98        let (to, call_data) = self.swap_step_encoder.to_call_data(&swap_opcodes)?;
99
100        Ok((to, None, call_data, tips_vec))
101    }
102}