kabu_execution_multicaller/
swapstep_encoder.rs

1use alloy_primitives::{Address, Bytes, U256};
2use eyre::Result;
3use lazy_static::lazy_static;
4use tracing::trace;
5
6use crate::opcodes_encoder::{OpcodesEncoder, OpcodesEncoderV2};
7use crate::SwapLineEncoder;
8use kabu_defi_abi::AbiEncoderHelper;
9use kabu_types_blockchain::{MulticallerCall, MulticallerCalls};
10use kabu_types_entities::{SwapAmountType, SwapStep};
11
12lazy_static! {
13    static ref BALANCER_VAULT_ADDRESS: Address = "0xBA12222222228d8Ba445958a75a0704d566BF2C8".parse().unwrap();
14}
15
16#[derive(Clone)]
17pub struct SwapStepEncoder {
18    pub multicaller_address: Address,
19    pub swap_line_encoder: SwapLineEncoder,
20}
21
22impl SwapStepEncoder {
23    pub fn new(multicaller_address: Address, swap_line_encoder: SwapLineEncoder) -> Self {
24        Self { multicaller_address, swap_line_encoder }
25    }
26
27    pub fn default_with_address(multicaller_address: Address) -> Self {
28        let swap_line_encoder = SwapLineEncoder::default_with_address(multicaller_address);
29        Self { multicaller_address, swap_line_encoder }
30    }
31
32    pub fn get_contract_address(&self) -> Address {
33        self.multicaller_address
34    }
35
36    pub fn encode_do_calls(&self, opcodes: MulticallerCalls, inside_opcodes: MulticallerCalls) -> Result<MulticallerCalls> {
37        let mut opcodes = opcodes;
38        let call_bytes = OpcodesEncoderV2::pack_do_calls(&inside_opcodes)?;
39        opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes));
40        Ok(opcodes)
41    }
42
43    pub fn encode_tips(
44        &self,
45        swap_opcodes: MulticallerCalls,
46        token_address: Address,
47        min_balance: U256,
48        tips: U256,
49        funds_to: Address,
50    ) -> Result<MulticallerCalls> {
51        self.swap_line_encoder.encode_tips(swap_opcodes, token_address, min_balance, tips, funds_to)
52    }
53
54    pub fn encode_balancer_flash_loan(&self, steps: Vec<SwapStep>) -> Result<MulticallerCalls> {
55        let flash_funds_to = self.multicaller_address;
56
57        let mut swap_opcodes = MulticallerCalls::new();
58
59        let first_swap = &steps[0];
60
61        let mut steps = steps.clone();
62
63        let token = first_swap.first_token().unwrap();
64        let in_amount = first_swap.get_in_amount().unwrap();
65
66        for (swap_idx, swap) in steps.iter_mut().enumerate() {
67            if swap_idx > 0 {
68                swap.get_mut_swap_line_by_index(swap.len() - 1).amount_in = SwapAmountType::Balance(flash_funds_to);
69            }
70
71            if swap.swap_line_vec().len() == 1 {
72                swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount(swap.swap_line_vec().first().unwrap(), None)?);
73            } else {
74                for swap_path in swap.swap_line_vec().iter() {
75                    let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?;
76                    let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?;
77                    swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes));
78                }
79            }
80        }
81
82        let inside_call_bytes = OpcodesEncoderV2::pack_do_calls_data(&swap_opcodes)?;
83
84        let mut flash_opcodes = MulticallerCalls::new();
85
86        let flash_call_data =
87            AbiEncoderHelper::encode_balancer_flashloan(token.get_address(), in_amount, inside_call_bytes, self.multicaller_address);
88
89        flash_opcodes.add(MulticallerCall::new_call(*BALANCER_VAULT_ADDRESS, &flash_call_data));
90
91        Ok(flash_opcodes)
92    }
93
94    pub fn encode_in_amount(&self, flash_step: SwapStep, swap_step: SwapStep) -> Result<MulticallerCalls> {
95        let mut swap_step = swap_step;
96
97        //let flash_funds_to = self.multicaller_address;
98
99        if flash_step.len() > 1 || swap_step.len() > 1 {
100            swap_step.get_mut_swap_line_by_index(swap_step.len() - 1).amount_in = SwapAmountType::Balance(self.multicaller_address);
101        }
102
103        let mut swap_opcodes = MulticallerCalls::new();
104
105        if swap_step.swap_line_vec().len() == 1 {
106            trace!("swap.swap_line_vec().len() == 1");
107            swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount(swap_step.swap_line_vec().first().unwrap(), None)?);
108        } else {
109            trace!("swap.swap_line_vec().len() != 1");
110            for swap_path in swap_step.swap_line_vec().iter() {
111                let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?;
112                let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?;
113                swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes));
114
115                //swap_opcodes.merge( self.swap_path_encoder.encode_swap_in_amount(swap_path, flash_funds_to, self.multicaller)?);
116                //let pop_opcode = Opcode::new_calculation_call(&Bytes::from(vec![0x8,0x8,0x11,0]));
117                //swap_opcodes.add(pop_opcode);
118            }
119        }
120
121        let flash_funds_to = swap_step.get_first_pool();
122
123        let mut flash_swaps = flash_step.swap_line_vec().clone();
124        flash_swaps.reverse();
125
126        for flash_swap_path in flash_swaps.iter() {
127            swap_opcodes = self.swap_line_encoder.encode_flash_swap_line_in_amount(flash_swap_path, swap_opcodes, flash_funds_to)?;
128        }
129
130        Ok(swap_opcodes)
131    }
132
133    pub fn encode_out_amount(&self, swap_step: SwapStep, flash_step: SwapStep) -> Result<MulticallerCalls> {
134        let mut swap_opcodes = MulticallerCalls::new();
135
136        if swap_step.swap_line_vec().len() == 1 {
137            swap_opcodes.merge(
138                self.swap_line_encoder
139                    .encode_swap_line_in_amount(swap_step.swap_line_vec().first().unwrap(), flash_step.get_first_pool())?,
140            );
141        } else {
142            for swap_path in swap_step.swap_line_vec().iter() {
143                let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?;
144                let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?;
145                swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes));
146
147                //swap_opcodes.merge( self.swap_path_encoder.encode_swap_in_amount(swap_path, flash_funds_to, self.multicaller)?);
148                //let pop_opcode = Opcode::new_calculation_call(&Bytes::from(vec![0x8,0x8,0x11,0]));
149                //swap_opcodes.add(pop_opcode);
150            }
151        }
152
153        let mut flash_swaps = flash_step.swap_line_vec().clone();
154        flash_swaps.reverse();
155
156        for flash_swap_path in flash_swaps.iter() {
157            swap_opcodes = self.swap_line_encoder.encode_flash_swap_line_out_amount(flash_swap_path, swap_opcodes)?;
158        }
159
160        Ok(swap_opcodes)
161    }
162
163    pub fn to_call_data(&self, opcodes: &MulticallerCalls) -> Result<(Address, Bytes)> {
164        let call_data = OpcodesEncoderV2::pack_do_calls(opcodes)?;
165        Ok((self.multicaller_address, call_data))
166    }
167
168    pub fn encode_swap_steps(&self, sp0: &SwapStep, sp1: &SwapStep) -> Result<MulticallerCalls> {
169        if sp0.can_flash_swap() {
170            trace!("encode_swap_steps -> sp0.can_flash_swap()");
171            self.encode_in_amount(sp0.clone(), sp1.clone())
172        } else if sp1.can_flash_swap() {
173            trace!("encode_swap_steps -> sp1.can_flash_swap()");
174            self.encode_out_amount(sp0.clone(), sp1.clone())
175        } else {
176            trace!("encode_swap_steps -> encode_balancer_flash_loan");
177            self.encode_balancer_flash_loan(vec![sp0.clone(), sp1.clone()])
178        }
179    }
180
181    fn add_calls_with_optional_value(&self, calls: &mut MulticallerCalls, call_list: Vec<(Address, Bytes, Option<U256>)>) {
182        for (to, data, value) in call_list {
183            if let Some(value) = value {
184                calls.add(MulticallerCall::new_call_with_value(to, &data, value));
185            } else {
186                calls.add(MulticallerCall::new_call(to, &data));
187            }
188        }
189    }
190}