kabu_execution_multicaller/pool_abi_encoder/pools/
uniswapv3.rs1use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait;
2use alloy_primitives::{Address, Bytes, I256, U160, U256};
3use alloy_sol_types::SolInterface;
4use kabu_defi_abi::uniswap3::IUniswapV3Pool;
5use kabu_types_market::Pool;
6use lazy_static::lazy_static;
7use std::ops::Sub;
8
9lazy_static! {
10 static ref LOWER_LIMIT: U160 = U160::from(4295128740u64);
11 static ref UPPER_LIMIT: U160 = U160::from_str_radix("1461446703485210103287273052203988822378723970341", 10).unwrap();
12}
13
14pub struct UniswapV3ProtocolAbiEncoder;
15impl UniswapV3ProtocolAbiEncoder {
16 pub fn get_zero_for_one(token_address_from: &Address, token_address_to: &Address) -> bool {
17 token_address_from < token_address_to
18 }
19
20 pub fn get_price_limit(token_address_from: &Address, token_address_to: &Address) -> U160 {
21 if token_address_from < token_address_to { *LOWER_LIMIT } else { *UPPER_LIMIT }
22 }
23}
24
25impl ProtocolAbiSwapEncoderTrait for UniswapV3ProtocolAbiEncoder {
26 fn encode_swap_in_amount_provided(
27 &self,
28 _pool: &dyn Pool,
29 token_from_address: Address,
30 token_to_address: Address,
31 amount: U256,
32 recipient: Address,
33 payload: Bytes,
34 ) -> eyre::Result<Bytes> {
35 let zero_for_one = UniswapV3ProtocolAbiEncoder::get_zero_for_one(&token_from_address, &token_to_address);
36 let sqrt_price_limit_x96 = UniswapV3ProtocolAbiEncoder::get_price_limit(&token_from_address, &token_to_address);
37 let swap_call = IUniswapV3Pool::swapCall {
38 recipient,
39 zeroForOne: zero_for_one,
40 amountSpecified: I256::from_raw(amount),
41 sqrtPriceLimitX96: sqrt_price_limit_x96,
42 data: payload,
43 };
44
45 Ok(Bytes::from(IUniswapV3Pool::IUniswapV3PoolCalls::swap(swap_call).abi_encode()))
46 }
47
48 fn encode_swap_out_amount_provided(
49 &self,
50 _pool: &dyn Pool,
51 token_from_address: Address,
52 token_to_address: Address,
53 amount: U256,
54 recipient: Address,
55 payload: Bytes,
56 ) -> eyre::Result<Bytes> {
57 let zero_for_one = UniswapV3ProtocolAbiEncoder::get_zero_for_one(&token_from_address, &token_to_address);
58 let sqrt_price_limit_x96 = UniswapV3ProtocolAbiEncoder::get_price_limit(&token_from_address, &token_to_address);
59 let swap_call = IUniswapV3Pool::swapCall {
60 recipient,
61 zeroForOne: zero_for_one,
62 amountSpecified: I256::ZERO.sub(I256::from_raw(amount)),
63 sqrtPriceLimitX96: sqrt_price_limit_x96,
64 data: payload,
65 };
66
67 Ok(Bytes::from(IUniswapV3Pool::IUniswapV3PoolCalls::swap(swap_call).abi_encode()))
68 }
69
70 fn swap_in_amount_offset(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
71 Some(0x44)
72 }
73
74 fn swap_out_amount_offset(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
75 Some(0x44)
76 }
77
78 fn swap_out_amount_return_offset(&self, _pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
79 if Self::get_zero_for_one(&token_from_address, &token_to_address) { Some(0x20) } else { Some(0x0) }
80 }
81
82 fn swap_in_amount_return_offset(&self, _pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
83 if Self::get_zero_for_one(&token_from_address, &token_to_address) { Some(0x20) } else { Some(0x0) }
84 }
85
86 fn swap_in_amount_return_script(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
87 Some(Bytes::from(vec![0x8, 0x2A, 0x00]))
88 }
89 fn swap_out_amount_return_script(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
90 None
91 }
92}