Skip to main content

evm_dex_pool/pool/
base.rs

1use crate::contracts::{IAlgebraFactory, IUniswapV2Factory, IUniswapV3Factory, IVeloPoolFactory};
2use crate::erc4626::ERC4626Pool;
3use crate::erc4626::VerioIP;
4use crate::lb::LBPool;
5use crate::v2::UniswapV2Pool;
6use crate::v3::UniswapV3Pool;
7use alloy::sol_types::SolEvent;
8use alloy::{
9    primitives::{Address, FixedBytes, U256},
10    rpc::types::Log,
11};
12use anyhow::Result;
13use serde::{Deserialize, Serialize};
14use std::any::Any;
15
16pub type Topic = FixedBytes<32>;
17
18/// Interface for pool operations, implemented by all pool types (V2, V3, etc.)
19pub trait PoolTypeTrait: Send + Sync {
20    fn pool_type(&self) -> PoolType;
21}
22
23pub trait PoolInterface: std::fmt::Debug + Send + Sync + PoolTypeTrait + EventApplicable {
24    /// Calculate output amount for a swap given an input amount and token
25    fn calculate_output(&self, token_in: &Address, amount_in: U256) -> Result<U256>;
26
27    /// Calculate input amount for a swap given an output amount and token
28    fn calculate_input(&self, token_out: &Address, amount_out: U256) -> Result<U256>;
29
30    /// Apply a swap to the pool state
31    fn apply_swap(&mut self, token_in: &Address, amount_in: U256, amount_out: U256) -> Result<()>;
32
33    /// Get the pool address
34    fn address(&self) -> Address;
35
36    /// Get the tokens in the pool
37    fn tokens(&self) -> (Address, Address);
38
39    /// Get token0 of the pool
40    fn token0(&self) -> Address {
41        self.tokens().0
42    }
43
44    /// Get token1 of the pool
45    fn token1(&self) -> Address {
46        self.tokens().1
47    }
48
49    /// Get the pool fee as a fraction (e.g., 0.003 for 0.3%)
50    fn fee(&self) -> f64;
51
52    fn fee_raw(&self) -> u64;
53
54    /// Get a unique identifier for the pool
55    fn id(&self) -> String;
56
57    /// Check if the pool contains a token
58    fn contains_token(&self, token: &Address) -> bool;
59
60    /// Clone the pool interface to a box
61    fn clone_box(&self) -> Box<dyn PoolInterface + Send + Sync>;
62
63    /// Log summary of the pool
64    fn log_summary(&self) -> String;
65
66    /// Helper method for downcasting
67    fn as_any(&self) -> &dyn Any;
68    fn as_any_mut(&mut self) -> &mut dyn Any;
69}
70
71impl dyn PoolInterface + Send + Sync {
72    /// Downcast to a concrete pool type
73    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
74        self.as_any().downcast_ref::<T>()
75    }
76
77    /// Downcast to a concrete pool type (mutable)
78    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
79        self.as_any_mut().downcast_mut::<T>()
80    }
81}
82
83/// Pool type enum
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub enum PoolType {
86    /// Uniswap V2-compatible pool (constant product formula)
87    UniswapV2,
88    /// Uniswap V3-compatible pool (concentrated liquidity)
89    UniswapV3,
90    /// ERC4626-compatible pool
91    ERC4626(ERC4626Pool),
92    /// TraderJoe Liquidity Book pool (bin-based AMM)
93    TraderJoeLB,
94}
95
96impl std::fmt::Display for PoolType {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match self {
99            PoolType::UniswapV2 => write!(f, "uniswap_v2"),
100            PoolType::UniswapV3 => write!(f, "uniswap_v3"),
101            PoolType::ERC4626(ERC4626Pool::VerioIP) => write!(f, "verio_ip"),
102            PoolType::TraderJoeLB => write!(f, "traderjoe_liquidity_book"),
103        }
104    }
105}
106
107impl From<PoolType> for String {
108    fn from(pool_type: PoolType) -> Self {
109        pool_type.to_string()
110    }
111}
112
113impl Default for PoolType {
114    fn default() -> Self {
115        PoolType::UniswapV2
116    }
117}
118
119impl PoolType {
120    pub fn topics(&self) -> Vec<FixedBytes<32>> {
121        match self {
122            Self::UniswapV2 => UniswapV2Pool::topics(),
123            Self::UniswapV3 => UniswapV3Pool::topics(),
124            Self::ERC4626(ERC4626Pool::VerioIP) => VerioIP::topics(),
125            Self::TraderJoeLB => LBPool::topics(),
126        }
127    }
128
129    pub fn profitable_topics(&self) -> Vec<FixedBytes<32>> {
130        match self {
131            Self::UniswapV2 => UniswapV2Pool::profitable_topics(),
132            Self::UniswapV3 => UniswapV3Pool::profitable_topics(),
133            Self::ERC4626(ERC4626Pool::VerioIP) => VerioIP::profitable_topics(),
134            Self::TraderJoeLB => LBPool::profitable_topics(),
135        }
136    }
137}
138
139/// Trait for applying events to pool state
140pub trait EventApplicable {
141    /// Apply an event to update the pool state
142    fn apply_log(&mut self, event: &Log) -> Result<()>;
143}
144
145pub trait TopicList {
146    fn topics() -> Vec<Topic>;
147
148    fn profitable_topics() -> Vec<Topic>;
149}
150
151pub const POOL_CREATED_TOPICS: &[Topic] = &[
152    IUniswapV2Factory::PairCreated::SIGNATURE_HASH,
153    IUniswapV3Factory::PoolCreated::SIGNATURE_HASH,
154    IAlgebraFactory::Pool::SIGNATURE_HASH,
155    IVeloPoolFactory::PoolCreated::SIGNATURE_HASH,
156];