kabu_strategy_backrun/
affected_pools_code.rs1use alloy_eips::BlockNumberOrTag;
2use alloy_evm::EvmEnv;
3use alloy_network::Network;
4use alloy_provider::Provider;
5use eyre::eyre;
6use tokio::sync::RwLock;
7
8use kabu_defi_pools::protocols::{UniswapV2Protocol, UniswapV3Protocol};
9use kabu_defi_pools::state_readers::UniswapV3EvmStateReader;
10use kabu_defi_pools::{MaverickPool, PancakeV3Pool, UniswapV2Pool, UniswapV3Pool};
11use kabu_evm_db::{AlloyDB, KabuDB};
12use kabu_types_blockchain::GethStateUpdateVec;
13use kabu_types_market::MarketState;
14use kabu_types_market::SwapDirection;
15use kabu_types_market::{Market, Pool, PoolId, PoolProtocol, PoolWrapper, get_protocol_by_factory};
16use std::collections::BTreeMap;
17use std::sync::Arc;
18use tracing::{debug, error};
19
20pub async fn get_affected_pools_from_code<P, N>(
21 client: P,
22 market: Arc<RwLock<Market>>,
23 state_update: &GethStateUpdateVec,
24 evm_env: &EvmEnv,
25) -> eyre::Result<BTreeMap<PoolWrapper, Vec<SwapDirection>>>
26where
27 N: Network,
28 P: Provider<N> + Send + Sync + Clone + 'static,
29{
30 let mut market_state = MarketState::new(KabuDB::new());
31
32 market_state.state_db.apply_geth_state_update(state_update, true, false);
33
34 let mut ret: BTreeMap<PoolWrapper, Vec<SwapDirection>> = BTreeMap::new();
35
36 for state_update_record in state_update.iter() {
37 for (address, state_update_entry) in state_update_record.iter() {
38 if let Some(code) = &state_update_entry.code {
39 if UniswapV2Protocol::is_code(code) {
40 match market.read().await.get_pool(&PoolId::Address(*address)) {
41 None => {
42 debug!(?address, "Loading UniswapV2 class pool");
43
44 let ext_db = AlloyDB::new(client.clone(), BlockNumberOrTag::Latest.into());
45
46 let Some(ext_db) = ext_db else {
47 error!("Cannot create AlloyDB");
48 continue;
49 };
50
51 let state_db = market_state.state_db.clone().with_ext_db(ext_db);
52
53 match UniswapV3EvmStateReader::factory(&state_db, evm_env, *address) {
54 Ok(_factory_address) => match UniswapV2Pool::fetch_pool_data_evm(&state_db, evm_env, *address) {
55 Ok(pool) => {
56 let pool = PoolWrapper::new(Arc::new(pool));
57 let protocol = pool.get_protocol();
58 let swap_directions = pool.get_swap_directions();
59
60 debug!(%address, %protocol, ?swap_directions, "UniswapV2 pool loaded");
61 ret.insert(pool, swap_directions);
62 }
63 Err(err) => {
64 error!(?address, %err, "Error loading UniswapV2 pool");
65 }
66 },
67 Err(err) => {
68 error!(?address, %err, "Error loading UniswapV2 factory for pool")
69 }
70 }
71 }
72 Some(pool) => {
73 debug!(?address, protocol = ?pool.get_protocol(), "Pool already exists");
74 }
75 }
76 }
77
78 if UniswapV3Protocol::is_code(code) {
79 match market.read().await.get_pool(&PoolId::Address(*address)) {
80 None => {
81 debug!(%address, "Loading UniswapV3 class pool");
82
83 let ext_db = AlloyDB::new(client.clone(), BlockNumberOrTag::Latest.into());
84
85 let Some(ext_db) = ext_db else {
86 error!("Cannot create AlloyDB");
87 continue;
88 };
89
90 let state_db = market_state.state_db.clone().with_ext_db(ext_db);
91
92 match UniswapV3EvmStateReader::factory(&state_db, evm_env, *address) {
93 Ok(factory_address) => {
94 match get_protocol_by_factory(factory_address) {
95 PoolProtocol::PancakeV3 => {
96 let pool = PancakeV3Pool::fetch_pool_data_evm(&state_db, evm_env, *address);
97 match pool {
98 Ok(pool) => {
99 let swap_directions = pool.get_swap_directions();
100 let protocol = pool.get_protocol();
101 debug!(?address, %protocol, ?swap_directions, "PancakeV3 Pool loaded");
102 ret.insert(PoolWrapper::new(Arc::new(pool)), swap_directions);
103 }
104 Err(err) => {
105 error!(?address, %err, "Error loading PancakeV3 pool");
106 }
107 }
108 }
109 PoolProtocol::Maverick => {
110 let pool = MaverickPool::fetch_pool_data_evm(&state_db, evm_env, *address);
111 match pool {
112 Ok(pool) => {
113 let pool = PoolWrapper::new(Arc::new(pool));
114 let swap_directions = pool.get_swap_directions();
115 let protocol = pool.get_protocol();
116 debug!(?address, %protocol, ?swap_directions, "Maverick Pool loaded");
117
118 ret.insert(pool, swap_directions);
119 }
120 Err(err) => {
121 error!(?address, %err, "Error loading Maverick pool");
122 }
123 }
124 }
125 _ => match UniswapV3Pool::fetch_pool_data_evm(&state_db, evm_env, *address) {
126 Ok(pool) => {
127 let pool = PoolWrapper::new(Arc::new(pool));
128 let swap_directions = pool.get_swap_directions();
129 let protocol = pool.get_protocol();
130 debug!(
131 %address,
132 %protocol,
133 ?swap_directions,
134 "UniswapV3 Pool loaded"
135 );
136 ret.insert(pool, swap_directions);
137 }
138 Err(err) => {
139 error!(%address, %err, "Error loading UniswapV3 pool");
140 }
141 },
142 };
143 }
144 Err(err) => {
145 error!(?address, %err, "Error loading UniswapV3 factory for pool")
146 }
147 }
148 }
149 Some(pool) => {
150 debug!(?address, protocol = ?pool.get_protocol(), "Pool already exists")
151 }
152 }
153 }
154 }
155 }
156 }
157 if !ret.is_empty() { Ok(ret) } else { Err(eyre!("NO_POOLS_LOADED")) }
158}
159
160pub fn is_pool_code(state_update: &GethStateUpdateVec) -> bool {
162 for state_update_record in state_update.iter() {
163 for (_address, state_update_entry) in state_update_record.iter() {
164 if let Some(code) = &state_update_entry.code {
165 if UniswapV3Protocol::is_code(code) {
166 return true;
167 }
168 if UniswapV2Protocol::is_code(code) {
169 return true;
170 }
171 }
172 }
173 }
174 false
175}