loom_types_entities/
swap.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::fmt::{Display, Formatter};
use std::sync::Arc;

use alloy_primitives::{Address, U256};

use crate::{SwapAmountType, SwapLine, SwapStep, Token};

#[derive(Clone, Debug)]
pub enum Swap {
    None,
    ExchangeSwapLine(SwapLine),
    BackrunSwapSteps((SwapStep, SwapStep)),
    BackrunSwapLine(SwapLine),
    Multiple(Vec<Swap>),
}

impl Display for Swap {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Swap::ExchangeSwapLine(path) => write!(f, "{path}"),
            Swap::BackrunSwapLine(path) => write!(f, "{path}"),
            Swap::BackrunSwapSteps((sp0, sp1)) => write!(f, "{sp0} {sp1}"),
            Swap::Multiple(_) => write!(f, "MULTIPLE_SWAP"),
            Swap::None => write!(f, "UNKNOWN_SWAP_TYPE"),
        }
    }
}

impl Swap {
    pub fn to_swap_steps(self: &Swap, multicaller: Address) -> Option<(SwapStep, SwapStep)> {
        match self {
            Swap::BackrunSwapLine(swap_line) => {
                let mut sp0: Option<SwapLine> = None;
                let mut sp1: Option<SwapLine> = None;

                for i in 1..swap_line.path.pool_count() {
                    let (flash_path, inside_path) = swap_line.split(i).unwrap();
                    if flash_path.can_flash_swap() || inside_path.can_flash_swap() {
                        sp0 = Some(flash_path);
                        sp1 = Some(inside_path);
                        break;
                    }
                }

                if sp0.is_none() || sp1.is_none() {
                    let (flash_path, inside_path) = swap_line.split(1).unwrap();
                    sp0 = Some(flash_path);
                    sp1 = Some(inside_path);
                }

                let mut step_0 = SwapStep::new(multicaller);
                step_0.add(sp0.unwrap());

                let mut step_1 = SwapStep::new(multicaller);
                let mut sp1 = sp1.unwrap();
                sp1.amount_in = SwapAmountType::Balance(multicaller);
                step_1.add(sp1);

                Some((step_0, step_1))
            }
            Swap::BackrunSwapSteps((sp0, sp1)) => Some((sp0.clone(), sp1.clone())),
            _ => None,
        }
    }

    pub fn abs_profit(&self) -> U256 {
        match self {
            Swap::BackrunSwapLine(path) => path.abs_profit(),
            Swap::BackrunSwapSteps((sp0, sp1)) => SwapStep::abs_profit(sp0, sp1),
            Swap::Multiple(swap_vec) => swap_vec.iter().map(|x| x.abs_profit()).sum(),
            Swap::None => U256::ZERO,
            Swap::ExchangeSwapLine(_) => U256::ZERO,
        }
    }

    pub fn pre_estimate_gas(&self) -> u64 {
        match self {
            Swap::ExchangeSwapLine(path) => path.gas_used.unwrap_or_default(),
            Swap::BackrunSwapLine(path) => path.gas_used.unwrap_or_default(),
            Swap::BackrunSwapSteps((sp0, sp1)) => {
                sp0.swap_line_vec().iter().map(|i| i.gas_used.unwrap_or_default()).sum::<u64>()
                    + sp1.swap_line_vec().iter().map(|i| i.gas_used.unwrap_or_default()).sum::<u64>()
            }
            Swap::Multiple(swap_vec) => swap_vec.iter().map(|x| x.pre_estimate_gas()).sum(),
            Swap::None => 0,
        }
    }

    pub fn abs_profit_eth(&self) -> U256 {
        match self {
            Swap::ExchangeSwapLine(_) => U256::ZERO,
            Swap::BackrunSwapLine(path) => path.abs_profit_eth(),
            Swap::BackrunSwapSteps((sp0, sp1)) => SwapStep::abs_profit_eth(sp0, sp1),
            Swap::Multiple(swap_vec) => swap_vec.iter().map(|x| x.abs_profit_eth()).sum(),
            Swap::None => U256::ZERO,
        }
    }

    pub fn get_first_token(&self) -> Option<&Arc<Token>> {
        match self {
            Swap::ExchangeSwapLine(swap_path) => swap_path.get_first_token(),
            Swap::BackrunSwapLine(swap_path) => swap_path.get_first_token(),
            Swap::BackrunSwapSteps((sp0, _sp1)) => sp0.get_first_token(),
            Swap::Multiple(_) => None,
            Swap::None => None,
        }
    }

    pub fn get_pool_address_vec(&self) -> Vec<Address> {
        match self {
            Swap::ExchangeSwapLine(swap_line) => swap_line.pools().iter().map(|item| item.get_address()).collect(),
            Swap::BackrunSwapLine(swap_line) => swap_line.pools().iter().map(|item| item.get_address()).collect(),
            Swap::BackrunSwapSteps((sp0, _sp1)) => {
                sp0.swap_line_vec().iter().flat_map(|item| item.pools().iter().map(|p| p.get_address()).collect::<Vec<_>>()).collect()
            }
            Swap::Multiple(swap_vec) => swap_vec.iter().flat_map(|x| x.get_pool_address_vec()).collect(),
            Swap::None => Vec::new(),
        }
    }
}