kabu_execution_multicaller/
swapstep_encoder.rs1use 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 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 }
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 }
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}