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_entities::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 {
22 *LOWER_LIMIT
23 } else {
24 *UPPER_LIMIT
25 }
26 }
27}
28
29impl ProtocolAbiSwapEncoderTrait for UniswapV3ProtocolAbiEncoder {
30 fn encode_swap_in_amount_provided(
31 &self,
32 _pool: &dyn Pool,
33 token_from_address: Address,
34 token_to_address: Address,
35 amount: U256,
36 recipient: Address,
37 payload: Bytes,
38 ) -> eyre::Result<Bytes> {
39 let zero_for_one = UniswapV3ProtocolAbiEncoder::get_zero_for_one(&token_from_address, &token_to_address);
40 let sqrt_price_limit_x96 = UniswapV3ProtocolAbiEncoder::get_price_limit(&token_from_address, &token_to_address);
41 let swap_call = IUniswapV3Pool::swapCall {
42 recipient,
43 zeroForOne: zero_for_one,
44 amountSpecified: I256::from_raw(amount),
45 sqrtPriceLimitX96: sqrt_price_limit_x96,
46 data: payload,
47 };
48
49 Ok(Bytes::from(IUniswapV3Pool::IUniswapV3PoolCalls::swap(swap_call).abi_encode()))
50 }
51
52 fn encode_swap_out_amount_provided(
53 &self,
54 _pool: &dyn Pool,
55 token_from_address: Address,
56 token_to_address: Address,
57 amount: U256,
58 recipient: Address,
59 payload: Bytes,
60 ) -> eyre::Result<Bytes> {
61 let zero_for_one = UniswapV3ProtocolAbiEncoder::get_zero_for_one(&token_from_address, &token_to_address);
62 let sqrt_price_limit_x96 = UniswapV3ProtocolAbiEncoder::get_price_limit(&token_from_address, &token_to_address);
63 let swap_call = IUniswapV3Pool::swapCall {
64 recipient,
65 zeroForOne: zero_for_one,
66 amountSpecified: I256::ZERO.sub(I256::from_raw(amount)),
67 sqrtPriceLimitX96: sqrt_price_limit_x96,
68 data: payload,
69 };
70
71 Ok(Bytes::from(IUniswapV3Pool::IUniswapV3PoolCalls::swap(swap_call).abi_encode()))
72 }
73
74 fn swap_in_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_offset(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
79 Some(0x44)
80 }
81
82 fn swap_out_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) {
84 Some(0x20)
85 } else {
86 Some(0x0)
87 }
88 }
89
90 fn swap_in_amount_return_offset(&self, _pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
91 if Self::get_zero_for_one(&token_from_address, &token_to_address) {
92 Some(0x20)
93 } else {
94 Some(0x0)
95 }
96 }
97
98 fn swap_in_amount_return_script(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
99 Some(Bytes::from(vec![0x8, 0x2A, 0x00]))
100 }
101 fn swap_out_amount_return_script(&self, _pool: &dyn Pool, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
102 None
103 }
104}