kabu_execution_multicaller/pool_opcodes_encoder/
uniswap3.rs1use crate::opcodes_helpers::OpcodesHelpers;
2use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait;
3use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload;
4use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait;
5use alloy_primitives::{Address, Bytes, U256};
6use eyre::{eyre, OptionExt};
7use kabu_defi_abi::AbiEncoderHelper;
8use kabu_types_blockchain::{MulticallerCall, MulticallerCalls};
9use kabu_types_entities::{Pool, PreswapRequirement, SwapAmountType};
10use tracing::trace;
11
12pub struct UniswapV3SwapOpcodesEncoder {}
13
14impl SwapOpcodesEncoderTrait for UniswapV3SwapOpcodesEncoder {
15 fn encode_swap_in_amount_provided(
16 &self,
17 swap_opcodes: &mut MulticallerCalls,
18 abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
19 token_from_address: Address,
20 token_to_address: Address,
21 amount_in: SwapAmountType,
22 cur_pool: &dyn Pool,
23 next_pool: Option<&dyn Pool>,
24 payload: MulticallerOpcodesPayload,
25 multicaller_address: Address,
26 ) -> eyre::Result<()> {
27 let inside_call_payload = if payload.is_empty() { Bytes::from(token_from_address.to_vec()) } else { payload.encode()? };
28
29 let swap_to: Address = if let Some(next_pool) = next_pool {
30 match next_pool.preswap_requirement() {
31 PreswapRequirement::Transfer(next_funds_to) => next_funds_to,
32 _ => multicaller_address,
33 }
34 } else {
35 multicaller_address
36 };
37
38 let pool_address = match cur_pool.get_address() {
39 kabu_types_entities::PoolId::Address(addr) => addr,
40 kabu_types_entities::PoolId::B256(_) => return Err(eyre!("Pool ID is B256, expected Address")),
41 };
42
43 let mut swap_opcode = MulticallerCall::new_call(
44 pool_address,
45 &abi_encoder.encode_swap_in_amount_provided(
46 cur_pool,
47 token_from_address,
48 token_to_address,
49 amount_in.unwrap_or_default(),
50 swap_to,
51 inside_call_payload,
52 )?,
53 );
54
55 swap_opcode.set_return_stack(
56 true,
57 0,
58 abi_encoder.swap_in_amount_return_offset(cur_pool, token_from_address, token_to_address).unwrap(),
59 0x20,
60 );
61
62 swap_opcodes.merge(OpcodesHelpers::build_call_stack(
63 amount_in,
64 swap_opcode,
65 abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).ok_or_eyre("NO_OFFSET")?,
66 0x20,
67 Some(token_from_address),
68 )?);
69
70 if next_pool.is_some() {
71 trace!("has next pool");
72 if let Some(x) = abi_encoder.swap_in_amount_return_script(cur_pool, token_from_address, token_to_address) {
73 let calc_opcode = MulticallerCall::new_calculation_call(&x);
74 swap_opcodes.add(calc_opcode);
75 }
76 }
77 Ok(())
78 }
79
80 fn encode_swap_out_amount_provided(
81 &self,
82 _swap_opcodes: &mut MulticallerCalls,
83 _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
84 _token_from_address: Address,
85 _token_to_address: Address,
86 _amount_out: SwapAmountType,
87 _cur_pool: &dyn Pool,
88 _next_pool: Option<&dyn Pool>,
89 _payload: MulticallerOpcodesPayload,
90 _multicaller_address: Address,
91 ) -> eyre::Result<()> {
92 Err(eyre!("NOT_IMPLEMENTED"))
93 }
94
95 fn encode_flash_swap_in_amount_provided(
96 &self,
97 swap_opcodes: &mut MulticallerCalls,
98 abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
99 token_from_address: Address,
100 token_to_address: Address,
101 amount_in: SwapAmountType,
102 flash_pool: &dyn Pool,
103 prev_pool: Option<&dyn Pool>,
104 payload: MulticallerOpcodesPayload,
105 multicaller_address: Address,
106 ) -> eyre::Result<()> {
107 let swap_to = match prev_pool {
108 Some(prev_pool) => match prev_pool.preswap_requirement() {
109 PreswapRequirement::Transfer(funds_to) => {
110 trace!("other transfer to previous pool: funds_to={:?}, prev_pool={:?}", funds_to, prev_pool.get_address());
111 funds_to
112 }
113 _ => {
114 trace!("other swap to multicaller, prev_pool={:?}", prev_pool.get_address());
115 multicaller_address
116 }
117 },
118 None => multicaller_address,
119 };
120
121 let payload = match payload {
122 MulticallerOpcodesPayload::Opcodes(payload) => {
123 trace!("uniswap v3 transfer token={:?}, to={:?}, amount={:?}", token_from_address, flash_pool.get_address(), amount_in);
124 let mut payload = payload;
125 let mut transfer_opcode = MulticallerCall::new_call(
126 token_from_address,
127 &AbiEncoderHelper::encode_erc20_transfer(
128 match flash_pool.get_address() {
129 kabu_types_entities::PoolId::Address(addr) => addr,
130 kabu_types_entities::PoolId::B256(_) => return Err(eyre!("Pool ID is B256, expected Address")),
131 },
132 amount_in.unwrap_or_default(),
133 ),
134 );
135
136 if amount_in.is_not_set() {
137 transfer_opcode.set_call_stack(false, 1, 0x24, 0x20);
138 }
139
140 payload.add(transfer_opcode);
141
142 MulticallerOpcodesPayload::Opcodes(payload)
143 }
144 _ => payload,
145 };
146
147 let inside_call_bytes = payload.encode()?;
148
149 trace!(
150 "uniswap v3 flash swap in amount for pool={:?} from {} to {} amount={:?}",
151 flash_pool.get_address(),
152 token_from_address,
153 token_to_address,
154 amount_in,
155 );
156 let pool_address = match flash_pool.get_address() {
157 kabu_types_entities::PoolId::Address(addr) => addr,
158 kabu_types_entities::PoolId::B256(_) => return Err(eyre!("Pool ID is B256, expected Address")),
159 };
160
161 let mut swap_opcode = MulticallerCall::new_call(
162 pool_address,
163 &abi_encoder.encode_swap_in_amount_provided(
164 flash_pool,
165 token_from_address,
166 token_to_address,
167 amount_in.unwrap_or_default(),
168 swap_to,
169 inside_call_bytes,
170 )?,
171 );
172
173 if amount_in.is_not_set() {
174 swap_opcode.set_call_stack(
175 false,
176 0,
177 abi_encoder.swap_in_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(),
178 0x20,
179 );
180 }
181
182 swap_opcodes.add(swap_opcode);
183
184 Ok(())
185 }
186
187 fn encode_flash_swap_out_amount_provided(
188 &self,
189 swap_opcodes: &mut MulticallerCalls,
190 abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
191 token_from_address: Address,
192 token_to_address: Address,
193 amount_out: SwapAmountType,
194 flash_pool: &dyn Pool,
195 next_pool: Option<&dyn Pool>,
196 payload: MulticallerOpcodesPayload,
197 multicaller_address: Address,
198 ) -> eyre::Result<()> {
199 let swap_to = next_pool.and_then(|next_pool| next_pool.preswap_requirement().address()).unwrap_or(multicaller_address);
200
201 let payload = if let MulticallerOpcodesPayload::Opcodes(inside_opcodes) = payload {
202 let mut inside_opcodes = inside_opcodes;
203 trace!("retflash transfer token={:?}, to={:?}, amount=stack_norel_1", token_from_address, flash_pool.get_address());
205 let mut transfer_opcode = MulticallerCall::new_call(
206 token_from_address,
207 &AbiEncoderHelper::encode_erc20_transfer(
208 match flash_pool.get_address() {
209 kabu_types_entities::PoolId::Address(addr) => addr,
210 kabu_types_entities::PoolId::B256(_) => return Err(eyre!("Pool ID is B256, expected Address")),
211 },
212 U256::ZERO,
213 ),
214 );
215 transfer_opcode.set_call_stack(false, 1, 0x24, 0x20);
216
217 inside_opcodes.add(transfer_opcode);
218
219 MulticallerOpcodesPayload::Opcodes(inside_opcodes)
220 } else {
221 payload
222 };
223
224 let inside_call_bytes = payload.encode()?;
225
226 trace!(
227 "uniswap v3 swap out amount provided for pool={:?}, from={} to={} amount_out={:?} receiver={} inside_opcodes_len={}",
228 flash_pool.get_address(),
229 token_from_address,
230 token_to_address,
231 amount_out,
232 swap_to,
233 inside_call_bytes.len()
234 );
235
236 let pool_address = match flash_pool.get_address() {
237 kabu_types_entities::PoolId::Address(addr) => addr,
238 kabu_types_entities::PoolId::B256(_) => return Err(eyre!("Pool ID is B256, expected Address")),
239 };
240
241 let mut swap_opcode = MulticallerCall::new_call(
242 pool_address,
243 &abi_encoder.encode_swap_out_amount_provided(
244 flash_pool,
245 token_from_address,
246 token_to_address,
247 amount_out.unwrap_or_default(),
248 swap_to,
249 inside_call_bytes,
250 )?,
251 );
252
253 if amount_out.is_not_set() {
254 trace!("uniswap v3 swap out amount is not set");
255
256 swap_opcode.set_call_stack(
257 true,
258 0,
259 abi_encoder.swap_out_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(),
260 0x20,
261 );
262
263 swap_opcodes.add(MulticallerCall::new_calculation_call(&Bytes::from(vec![0x2, 0x2A, 0x00])));
264 };
265
266 swap_opcodes.add(swap_opcode);
267
268 Ok(())
269 }
270}