kabu_types_market/
pool.rs

1use crate::PoolId;
2use crate::pool_error::PoolError;
3use crate::required_state::RequiredState;
4use crate::swap_direction::SwapDirection;
5use alloy_evm::EvmEnv;
6use alloy_primitives::{Address, Bytes, U256};
7use eyre::{Result, eyre};
8use kabu_defi_address_book::FactoryAddress;
9use kabu_evm_db::KabuDBError;
10use revm::DatabaseRef;
11use serde::{Deserialize, Serialize};
12use std::any::Any;
13use std::cmp::Ordering;
14use std::fmt::{Debug, Display, Formatter};
15use std::hash::{Hash, Hasher};
16use std::ops::Deref;
17use std::sync::Arc;
18use strum_macros::{Display, EnumIter, EnumString, VariantNames};
19
20pub fn get_protocol_by_factory(factory_address: Address) -> PoolProtocol {
21    if factory_address == FactoryAddress::UNISWAP_V2 {
22        PoolProtocol::UniswapV2
23    } else if factory_address == FactoryAddress::UNISWAP_V3 {
24        PoolProtocol::UniswapV3
25    } else if factory_address == FactoryAddress::PANCAKE_V3 {
26        PoolProtocol::PancakeV3
27    } else if factory_address == FactoryAddress::NOMISWAP {
28        PoolProtocol::NomiswapStable
29    } else if factory_address == FactoryAddress::ANTFARM {
30        PoolProtocol::AntFarm
31    } else if factory_address == FactoryAddress::SUSHISWAP_V2 {
32        PoolProtocol::Sushiswap
33    } else if factory_address == FactoryAddress::SUSHISWAP_V3 {
34        PoolProtocol::SushiswapV3
35    } else if factory_address == FactoryAddress::DOOARSWAP {
36        PoolProtocol::DooarSwap
37    } else if factory_address == FactoryAddress::SAFESWAP {
38        PoolProtocol::Safeswap
39    } else if factory_address == FactoryAddress::MINISWAP {
40        PoolProtocol::Miniswap
41    } else if factory_address == FactoryAddress::SHIBASWAP {
42        PoolProtocol::Shibaswap
43    } else if factory_address == FactoryAddress::MAVERICK {
44        PoolProtocol::Maverick
45    } else if factory_address == FactoryAddress::INTEGRAL {
46        PoolProtocol::Integral
47    } else {
48        PoolProtocol::Unknown
49    }
50}
51
52#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq, EnumString, VariantNames, Display, Default, Deserialize, Serialize, EnumIter)]
53#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
54pub enum PoolClass {
55    #[default]
56    #[serde(rename = "unknown")]
57    #[strum(serialize = "unknown")]
58    Unknown,
59    #[serde(rename = "uniswap2")]
60    #[strum(serialize = "uniswap2")]
61    UniswapV2,
62    #[serde(rename = "uniswap3")]
63    #[strum(serialize = "uniswap3")]
64    UniswapV3,
65    #[serde(rename = "uniswap4")]
66    #[strum(serialize = "uniswap4")]
67    UniswapV4,
68    #[serde(rename = "maverick")]
69    #[strum(serialize = "maverick")]
70    Maverick,
71    #[serde(rename = "maverick2")]
72    #[strum(serialize = "maverick2")]
73    MaverickV2,
74    #[serde(rename = "pancake3")]
75    #[strum(serialize = "pancake3")]
76    PancakeV3,
77    #[serde(rename = "curve")]
78    #[strum(serialize = "curve")]
79    Curve,
80    #[serde(rename = "steth")]
81    #[strum(serialize = "steth")]
82    LidoStEth,
83    #[serde(rename = "wsteth")]
84    #[strum(serialize = "wsteth")]
85    LidoWstEth,
86    #[serde(rename = "rocketpool")]
87    #[strum(serialize = "rocketpool")]
88    RocketPool,
89    #[serde(rename = "balancer1")]
90    #[strum(serialize = "balancer1")]
91    BalancerV1,
92    #[serde(rename = "balancer2")]
93    #[strum(serialize = "balancer2")]
94    BalancerV2,
95    #[serde(rename = "custom")]
96    #[strum(serialize = "custom")]
97    Custom(u64),
98}
99
100#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
101pub enum PoolProtocol {
102    Unknown,
103    AaveV2,
104    AaveV3,
105    UniswapV2,
106    UniswapV2Like,
107    NomiswapStable,
108    Sushiswap,
109    SushiswapV3,
110    DooarSwap,
111    OgPepe,
112    AntFarm,
113    Safeswap,
114    Miniswap,
115    Shibaswap,
116    UniswapV3,
117    UniswapV3Like,
118    UniswapV4,
119    PancakeV3,
120    Integral,
121    Maverick,
122    MaverickV2,
123    Curve,
124    LidoStEth,
125    LidoWstEth,
126    RocketEth,
127    BalancerV1,
128    BalancerV2,
129    Custom(u64),
130}
131
132impl Display for PoolProtocol {
133    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134        let protocol_name = match self {
135            Self::Unknown => "Unknown",
136            Self::AaveV2 => "AaveV2",
137            Self::AaveV3 => "AaveV3",
138            Self::UniswapV2 => "UniswapV2",
139            Self::UniswapV2Like => "UniswapV2Like",
140            Self::UniswapV3 => "UniswapV3",
141            Self::PancakeV3 => "PancakeV3",
142            Self::UniswapV4 => "UniswapV4",
143            Self::UniswapV3Like => "UniswapV3Like",
144            Self::NomiswapStable => "NomiswapStable",
145            Self::Sushiswap => "Sushiswap",
146            Self::SushiswapV3 => "SushiswapV3",
147            Self::DooarSwap => "Dooarswap",
148            Self::OgPepe => "OgPepe",
149            Self::AntFarm => "AntFarm",
150            Self::Miniswap => "Miniswap",
151            Self::Shibaswap => "Shibaswap",
152            Self::Safeswap => "Safeswap",
153            Self::Integral => "Integral",
154            Self::Maverick => "Maverick",
155            Self::MaverickV2 => "MaverickV2",
156            Self::Curve => "Curve",
157            Self::LidoWstEth => "WstEth",
158            Self::LidoStEth => "StEth",
159            Self::RocketEth => "RocketEth",
160            Self::BalancerV1 => "BalancerV1",
161            Self::BalancerV2 => "BalancerV2",
162            Self::Custom(_x) => "Custom",
163        };
164        write!(f, "{protocol_name}")
165    }
166}
167
168pub struct PoolWrapper {
169    pub pool: Arc<dyn Pool>,
170}
171
172impl PartialOrd for PoolWrapper {
173    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
174        Some(self.cmp(other))
175    }
176}
177
178impl Eq for PoolWrapper {}
179
180impl Ord for PoolWrapper {
181    fn cmp(&self, other: &Self) -> Ordering {
182        self.get_pool_id().cmp(&other.get_pool_id())
183    }
184}
185
186impl Display for PoolWrapper {
187    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
188        write!(f, "{}@{}", self.get_protocol(), self.get_pool_id())
189    }
190}
191
192impl Debug for PoolWrapper {
193    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
194        write!(f, "{}@{}", self.get_protocol(), self.get_pool_id())
195    }
196}
197
198impl Hash for PoolWrapper {
199    fn hash<H: Hasher>(&self, state: &mut H) {
200        self.get_pool_id().hash(state)
201    }
202}
203
204impl PartialEq for PoolWrapper {
205    fn eq(&self, other: &Self) -> bool {
206        self.pool.get_pool_id() == other.pool.get_pool_id()
207    }
208}
209
210impl Clone for PoolWrapper {
211    fn clone(&self) -> Self {
212        Self { pool: self.pool.clone() }
213    }
214}
215
216impl Deref for PoolWrapper {
217    type Target = dyn Pool;
218
219    fn deref(&self) -> &Self::Target {
220        self.pool.deref()
221    }
222}
223
224impl AsRef<dyn Pool> for PoolWrapper {
225    fn as_ref(&self) -> &(dyn Pool + 'static) {
226        self.pool.as_ref()
227    }
228}
229
230impl PoolWrapper {
231    pub fn new(pool: Arc<dyn Pool>) -> Self {
232        PoolWrapper { pool }
233    }
234}
235
236impl<T: 'static + Pool> From<T> for PoolWrapper {
237    fn from(pool: T) -> Self {
238        Self { pool: Arc::new(pool) }
239    }
240}
241
242pub trait Pool: Sync + Send {
243    fn as_any(&self) -> &dyn Any;
244
245    fn get_class(&self) -> PoolClass;
246
247    fn get_protocol(&self) -> PoolProtocol;
248
249    fn get_address(&self) -> PoolId;
250
251    fn get_pool_id(&self) -> PoolId;
252
253    fn get_fee(&self) -> U256;
254
255    fn get_tokens(&self) -> Vec<Address>;
256
257    fn get_swap_directions(&self) -> Vec<SwapDirection>;
258
259    fn calculate_out_amount(
260        &self,
261        db: &dyn DatabaseRef<Error = KabuDBError>,
262        evm_env: &EvmEnv,
263        token_address_from: &Address,
264        token_address_to: &Address,
265        in_amount: U256,
266    ) -> Result<(U256, u64), PoolError>;
267
268    // returns (in_amount, gas_used)
269    fn calculate_in_amount(
270        &self,
271        db: &dyn DatabaseRef<Error = KabuDBError>,
272        evm_env: &EvmEnv,
273        token_address_from: &Address,
274        token_address_to: &Address,
275        out_amount: U256,
276    ) -> Result<(U256, u64), PoolError>;
277
278    fn can_flash_swap(&self) -> bool;
279
280    fn can_calculate_in_amount(&self) -> bool;
281
282    fn get_abi_encoder(&self) -> Option<&dyn PoolAbiEncoder>;
283
284    fn get_read_only_cell_vec(&self) -> Vec<U256>;
285
286    fn get_state_required(&self) -> Result<RequiredState>;
287
288    fn is_native(&self) -> bool;
289
290    fn preswap_requirement(&self) -> PreswapRequirement;
291
292    fn get_pool_manager_cells(&self) -> Vec<(Address, Vec<U256>)> {
293        vec![]
294    }
295}
296
297pub struct DefaultAbiSwapEncoder {}
298
299impl PoolAbiEncoder for DefaultAbiSwapEncoder {}
300
301#[derive(Clone, Debug)]
302pub enum PreswapRequirement {
303    Unknown,
304    Transfer(Address),
305    Allowance,
306    Callback,
307    Base,
308}
309
310impl PartialEq for PreswapRequirement {
311    fn eq(&self, other: &Self) -> bool {
312        match (self, other) {
313            (PreswapRequirement::Unknown, PreswapRequirement::Unknown) => true,
314            (PreswapRequirement::Transfer(addr1), PreswapRequirement::Transfer(addr2)) => addr1 == addr2,
315            (PreswapRequirement::Allowance, PreswapRequirement::Allowance) => true,
316            (PreswapRequirement::Callback, PreswapRequirement::Callback) => true,
317            (PreswapRequirement::Base, PreswapRequirement::Base) => true,
318            _ => false,
319        }
320    }
321}
322
323impl PreswapRequirement {
324    pub fn address_or(&self, default_address: Address) -> Address {
325        match self {
326            PreswapRequirement::Transfer(address) => *address,
327            _ => default_address,
328        }
329    }
330    pub fn address(&self) -> Option<Address> {
331        match self {
332            PreswapRequirement::Transfer(address) => Some(*address),
333            _ => None,
334        }
335    }
336}
337
338pub trait PoolAbiEncoder: Send + Sync {
339    fn encode_swap_in_amount_provided(
340        &self,
341        _token_from_address: Address,
342        _token_to_address: Address,
343        _amount: U256,
344        _recipient: Address,
345        _payload: Bytes,
346    ) -> Result<Bytes> {
347        Err(eyre!("NOT_IMPLEMENTED"))
348    }
349    fn encode_swap_out_amount_provided(
350        &self,
351        _token_from_address: Address,
352        _token_to_address: Address,
353        _amount: U256,
354        _recipient: Address,
355        _payload: Bytes,
356    ) -> Result<Bytes> {
357        Err(eyre!("NOT_IMPLEMENTED"))
358    }
359
360    fn swap_in_amount_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
361        None
362    }
363    fn swap_out_amount_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
364        None
365    }
366    fn swap_out_amount_return_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
367        None
368    }
369    fn swap_in_amount_return_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
370        None
371    }
372    fn swap_out_amount_return_script(&self, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
373        None
374    }
375    fn swap_in_amount_return_script(&self, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
376        None
377    }
378}
379
380#[cfg(test)]
381mod tests {
382    use crate::PoolClass;
383
384    #[test]
385    fn test_strum() {
386        println!("{}", PoolClass::Unknown);
387        println!("{}", PoolClass::UniswapV2);
388    }
389}