loom_execution_multicaller/
swap_encoder.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::MulticallerSwapEncoder;
use alloy_primitives::{Address, BlockNumber, Bytes, U256};
use eyre::{eyre, OptionExt, Result};
use loom_types_blockchain::MulticallerCalls;
use loom_types_entities::tips::{tips_and_value_for_swap_type, Tips};
use loom_types_entities::{Swap, SwapEncoder, SwapStep};
use tracing::{debug, error, trace};

impl SwapEncoder for MulticallerSwapEncoder {
    fn encode(
        &self,
        swap: Swap,
        tips_pct: Option<u32>,
        _next_block_number: Option<BlockNumber>,
        gas_cost: Option<U256>,
        sender_address: Option<Address>,
        sender_eth_balance: Option<U256>,
    ) -> Result<(Address, Option<U256>, Bytes, Vec<Tips>)> {
        let swap_vec = match &swap {
            Swap::BackrunSwapLine(_) | Swap::BackrunSwapSteps(_) => {
                vec![swap.to_swap_steps(self.swap_step_encoder.get_contract_address()).ok_or_eyre("SWAP_TYPE_NOTE_COVERED")?]
            }
            Swap::Multiple(swap_vec) => {
                let mut ret: Vec<(SwapStep, SwapStep)> = Vec::new();
                for s in swap_vec.iter() {
                    ret.push(s.to_swap_steps(self.swap_step_encoder.get_contract_address()).ok_or_eyre("AA")?);
                }
                ret
            }
            Swap::ExchangeSwapLine(_) => vec![],
            Swap::None => {
                vec![]
            }
        };

        let mut swap_steps = "".to_string();
        for (level, (sp0, sp1)) in swap_vec.iter().enumerate() {
            swap_steps.push_str(format!("{}{} \n{}\t-> {}\n", "\t".repeat(level), sp0, "\t".repeat(level), sp1).as_str());
        }
        debug!("Swaps:\n{}", swap_steps);

        let mut swap_opcodes = if swap_vec.is_empty() {
            match &swap {
                Swap::ExchangeSwapLine(swap_line) => {
                    trace!("START: exchange swap line");
                    match self.swap_step_encoder.swap_line_encoder.encode_swap_line_in_amount(
                        swap_line,
                        self.swap_step_encoder.get_contract_address(),
                        self.swap_step_encoder.get_contract_address(),
                    ) {
                        Ok(calls) => calls,
                        Err(e) => {
                            error!("swap_line_encoder.encode_swap_line_in_amount : {}", e);
                            return Err(eyre!("ENCODING_FAILED"));
                        }
                    }
                }
                _ => return Err(eyre!("NO_SWAP_STEPS")),
            }
        } else if swap_vec.len() == 1 {
            trace!("START: encode_swap_steps two-hop");
            let sp0 = &swap_vec[0].0;
            let sp1 = &swap_vec[0].1;
            self.swap_step_encoder.encode_swap_steps(sp0, sp1)?
        } else {
            trace!("START: encode_swap_steps multi-hop");
            let mut ret = MulticallerCalls::new();
            for (sp0, sp1) in swap_vec.iter() {
                ret = self.swap_step_encoder.encode_do_calls(ret, self.swap_step_encoder.encode_swap_steps(sp0, sp1)?)?;
            }
            ret
        };
        trace!("END: swap_opcodes");

        let tips_vec =
            if let (Some(tips_pct), Some(sender_address), Some(sender_eth_balance)) = (tips_pct, sender_address, sender_eth_balance) {
                let (tips_vec, _call_value) = tips_and_value_for_swap_type(&swap, Some(tips_pct), gas_cost, sender_eth_balance)?;
                for tips in &tips_vec {
                    swap_opcodes = self.swap_step_encoder.encode_tips(
                        swap_opcodes,
                        tips.token_in.get_address(),
                        tips.min_change,
                        tips.tips,
                        sender_address,
                    )?;
                }
                tips_vec
            } else {
                vec![]
            };

        let (to, call_data) = self.swap_step_encoder.to_call_data(&swap_opcodes)?;

        Ok((to, None, call_data, tips_vec))
    }
}