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