kabu_defi_pools/protocols/
curve.rs

1use std::fmt::{Display, Formatter};
2use std::marker::PhantomData;
3
4use alloy::primitives::{address, Address, Bytes, U256};
5use alloy::providers::{Network, Provider};
6use alloy::rpc::types::{BlockId, BlockNumberOrTag};
7use alloy::sol_types::SolInterface;
8use eyre::{eyre, Report, Result};
9use tracing::{debug, error, trace};
10
11use kabu_defi_abi::curve::ICurveAddressProvider::ICurveAddressProviderInstance;
12use kabu_defi_abi::curve::ICurveCommon::ICurveCommonInstance;
13use kabu_defi_abi::curve::ICurveCommonI128::ICurveCommonI128Instance;
14use kabu_defi_abi::curve::ICurveFactory::ICurveFactoryInstance;
15use kabu_defi_abi::curve::ICurveI128_2::ICurveI128_2Instance;
16use kabu_defi_abi::curve::ICurveI128_2_To::{ICurveI128_2_ToCalls, ICurveI128_2_ToInstance};
17use kabu_defi_abi::curve::ICurveI128_2_To_Meta::ICurveI128_2_To_MetaInstance;
18use kabu_defi_abi::curve::ICurveI128_3::{ICurveI128_3Calls, ICurveI128_3Instance};
19use kabu_defi_abi::curve::ICurveI128_4::{ICurveI128_4Calls, ICurveI128_4Instance};
20use kabu_defi_abi::curve::ICurveU256_2::{ICurveU256_2Calls, ICurveU256_2Instance};
21use kabu_defi_abi::curve::ICurveU256_2_Eth_To::{ICurveU256_2_Eth_ToCalls, ICurveU256_2_Eth_ToInstance};
22use kabu_defi_abi::curve::ICurveU256_2_To::{ICurveU256_2_ToCalls, ICurveU256_2_ToInstance};
23use kabu_defi_abi::curve::ICurveU256_3_Eth::{ICurveU256_3_EthCalls, ICurveU256_3_EthInstance};
24use kabu_defi_abi::curve::ICurveU256_3_Eth_To::{ICurveU256_3_Eth_ToCalls, ICurveU256_3_Eth_ToInstance};
25use kabu_defi_abi::curve::ICurveU256_3_Eth_To2::{ICurveU256_3_Eth_To2Calls, ICurveU256_3_Eth_To2Instance};
26use kabu_defi_abi::curve::{
27    ICurveI128_2, ICurveI128_2_To, ICurveI128_2_To_Meta, ICurveI128_3, ICurveI128_4, ICurveU256_2, ICurveU256_2_Eth_To, ICurveU256_2_To,
28    ICurveU256_3_Eth, ICurveU256_3_Eth_To, ICurveU256_3_Eth_To2,
29};
30
31#[derive(Clone, Debug)]
32pub enum CurveContract<P, N>
33where
34    N: Network,
35    P: Provider<N> + Send + Sync + Clone + 'static,
36{
37    I128_2(ICurveI128_2Instance<P, N>),
38    I128_2To(ICurveI128_2_ToInstance<P, N>),
39    I128_2ToMeta(ICurveI128_2_To_MetaInstance<P, N>),
40    I128_3(ICurveI128_3Instance<P, N>),
41    I128_4(ICurveI128_4Instance<P, N>),
42    U256_2(ICurveU256_2Instance<P, N>),
43    U256_2To(ICurveU256_2_ToInstance<P, N>),
44    U256_2EthTo(ICurveU256_2_Eth_ToInstance<P, N>),
45    U256_3Eth(ICurveU256_3_EthInstance<P, N>),
46    U256_3EthTo(ICurveU256_3_Eth_ToInstance<P, N>),
47    U256_3EthTo2(ICurveU256_3_Eth_To2Instance<P, N>),
48}
49
50impl<P, N> Display for CurveContract<P, N>
51where
52    N: Network,
53    P: Provider<N> + Send + Sync + Clone + 'static,
54{
55    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
56        let contract_type = match self {
57            CurveContract::I128_2(_) => "I128_2",
58            CurveContract::I128_2To(_) => "I128_2_To",
59            CurveContract::I128_2ToMeta(_) => "I128_2_To_Meta",
60            CurveContract::I128_3(_) => "I128_3",
61            CurveContract::I128_4(_) => "I128_4",
62            CurveContract::U256_2(_) => "U256_2",
63            CurveContract::U256_2To(_) => "U256_2_To",
64            CurveContract::U256_2EthTo(_) => "U256_2_Eth_To",
65            CurveContract::U256_3Eth(_) => "U256_3_Eth",
66            CurveContract::U256_3EthTo(_) => "U256_3_Eth_To",
67            CurveContract::U256_3EthTo2(_) => "U256_3_Eth_To2",
68            //_ => "CurveUnknown"
69        };
70        write!(f, "{contract_type}")
71    }
72}
73
74pub struct CurveCommonContract<P, N>
75where
76    N: Network,
77    P: Provider<N> + Send + Sync + Clone + 'static,
78{
79    _pd: PhantomData<(P, N)>,
80}
81
82impl<P, N> CurveCommonContract<P, N>
83where
84    N: Network,
85    P: Provider<N> + Send + Sync + Clone + 'static,
86{
87    pub async fn lp_token(address: Address) -> Result<Address> {
88        if address == address!("bEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7") {
89            return Ok(address!("6c3F90f043a72FA612cbac8115EE7e52BDe6E490"));
90        }
91        Err(eyre!("NO_LP_TOKEN"))
92    }
93
94    pub async fn coin128(client: P, address: Address, coin_id: u32) -> Result<Address> {
95        let common_contract = ICurveCommonI128Instance::new(address, client);
96        match common_contract.coins(coin_id.into()).call_raw().await {
97            Ok(addr) => {
98                if addr.len() >= 32 {
99                    Ok(Address::from_slice(&addr[12..32]))
100                } else {
101                    Err(eyre!("CANNOT_GET_COIN_ADDRESS"))
102                }
103            }
104            Err(e) => {
105                trace!("coin call error {}", e);
106                Err(eyre!("CANNOT_GET_COIN_ADDRESS"))
107            }
108        }
109    }
110
111    pub async fn coin(client: P, address: Address, coin_id: u32) -> Result<Address> {
112        let common_contract = ICurveCommonInstance::new(address, client.clone());
113        match common_contract.coins(U256::from(coin_id)).call_raw().await {
114            Ok(addr) => {
115                if addr.len() >= 32 {
116                    Ok(Address::from_slice(&addr[12..32]))
117                } else {
118                    Self::coin128(client, address, coin_id).await
119                }
120            }
121            Err(e) => {
122                trace!("{e}");
123                Self::coin128(client, address, coin_id).await
124            }
125        }
126    }
127
128    pub async fn balance128(client: P, address: Address, coin_id: u32) -> Result<U256> {
129        let common_contract = ICurveCommonI128Instance::new(address, client);
130        match common_contract.balances(coin_id as i128).call_raw().await {
131            Ok(ret_data) => {
132                if ret_data.len() >= 32 {
133                    let balance = U256::from_be_slice(&ret_data[0..32]);
134                    Ok(balance)
135                } else {
136                    Err(eyre!("CANNOT_GET_COIN_BALANCE"))
137                }
138            }
139            Err(e) => {
140                trace!("balances128 call error {} : {}", coin_id, e);
141                Err(eyre!("CANNOT_GET_COIN_BALANCE"))
142            }
143        }
144    }
145
146    pub async fn balance(client: P, address: Address, coin_id: u32) -> Result<U256> {
147        let common_contract = ICurveCommonInstance::new(address, client.clone());
148        match common_contract.balances(U256::from(coin_id)).call_raw().await {
149            Ok(ret_data) => {
150                let balance = U256::from_be_slice(&ret_data[0..32]);
151                Ok(balance)
152            }
153            Err(e) => {
154                trace!("balances256 call error {} : {}", coin_id, e);
155                if coin_id == 0 {
156                    Self::balance128(client, address, coin_id).await
157                } else {
158                    Err(eyre!("CANNOT_GET_COIN_BALANCE"))
159                }
160            }
161        }
162    }
163    pub async fn coins(client: P, address: Address) -> Result<Vec<Address>> {
164        let mut ret: Vec<Address> = Vec::new();
165        for i in 0..4 {
166            match Self::coin(client.clone(), address, i).await {
167                Ok(coin_address) => ret.push(coin_address),
168                Err(_) => break,
169            }
170        }
171        if ret.is_empty() {
172            trace!("coin fetch coins");
173            Err(eyre!("CANNOT_GET_COIN_ADDRESS"))
174        } else {
175            trace!("coins @{} {:?}", address, ret);
176            Ok(ret)
177        }
178    }
179
180    pub async fn balances(client: P, address: Address) -> Result<Vec<U256>> {
181        let mut ret: Vec<U256> = Vec::new();
182
183        let common_contract = ICurveCommonInstance::new(address, client.clone());
184        match common_contract.get_balances().call().await {
185            Ok(return_bytes) => {
186                if return_bytes.0.len() < 64 {
187                    return Err(eyre!("CANNOT_FETCH_BALANCES"));
188                }
189                let balances_count = U256::from_be_slice(&return_bytes.0.to_vec()[0..32]);
190                for i in 0usize..balances_count.to() {
191                    let balance = U256::from_be_slice(&return_bytes.0.to_vec()[32 + i * 32..64 + i * 32]);
192                    ret.push(balance)
193                }
194                debug!("Curve Balances {:?} {:?}", address, ret);
195                Ok(ret)
196            }
197            Err(e) => {
198                for i in 0..4 {
199                    match Self::balance(client.clone(), address, i).await {
200                        Ok(balance) => ret.push(balance),
201                        Err(e) => {
202                            trace!("Error fetching coin balance {} : {}", i, e);
203                            break;
204                        }
205                    }
206                }
207                if ret.is_empty() {
208                    trace!("coin call error {}", e);
209                    Err(eyre!("CANNOT_GET_COIN_BALANCE"))
210                } else {
211                    Ok(ret)
212                }
213            }
214        }
215    }
216}
217
218impl<P, N> CurveContract<P, N>
219where
220    N: Network,
221    P: Provider<N> + Send + Sync + Clone + 'static,
222{
223    pub fn get_address(&self) -> Address {
224        match self {
225            CurveContract::I128_2(interface) => *interface.address(),
226
227            CurveContract::I128_2ToMeta(interface) => *interface.address(),
228
229            CurveContract::I128_2To(interface) => *interface.address(),
230            CurveContract::I128_3(interface) => *interface.address(),
231            CurveContract::I128_4(interface) => *interface.address(),
232            CurveContract::U256_2(interface) => *interface.address(),
233            CurveContract::U256_2To(interface) => *interface.address(),
234            CurveContract::U256_2EthTo(interface) => *interface.address(),
235            CurveContract::U256_3Eth(interface) => *interface.address(),
236            CurveContract::U256_3EthTo(interface) => *interface.address(),
237            CurveContract::U256_3EthTo2(interface) => *interface.address(),
238        }
239    }
240
241    pub fn can_exchange_to(&self) -> bool {
242        !(matches!(self, CurveContract::I128_3(_)) | matches!(self, CurveContract::U256_3Eth(_)))
243    }
244
245    pub fn can_calculate_in_amount(&self) -> bool {
246        matches!(
247            self,
248            CurveContract::I128_2To(_) | CurveContract::U256_2EthTo(_) | CurveContract::U256_3EthTo(_) | CurveContract::I128_2ToMeta(_)
249        )
250    }
251
252    pub async fn get_dy(&self, i: u32, j: u32, amount: U256) -> Result<U256> {
253        match self {
254            CurveContract::I128_2(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
255                Ok(x) => Ok(x),
256                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
257            },
258            CurveContract::I128_2ToMeta(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
259                Ok(x) => Ok(x),
260                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
261            },
262            CurveContract::I128_2To(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
263                Ok(x) => Ok(x),
264                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
265            },
266            CurveContract::I128_3(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
267                Ok(x) => Ok(x),
268                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
269            },
270            CurveContract::I128_4(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
271                Ok(x) => Ok(x),
272                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
273            },
274            CurveContract::U256_2(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
275                Ok(x) => Ok(x),
276                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
277            },
278            CurveContract::U256_2To(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
279                Ok(x) => Ok(x),
280                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
281            },
282            CurveContract::U256_2EthTo(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
283                Ok(x) => Ok(x),
284                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
285            },
286            CurveContract::U256_3EthTo(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
287                Ok(x) => Ok(x),
288                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
289            },
290            CurveContract::U256_3EthTo2(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
291                Ok(x) => Ok(x),
292                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
293            },
294            CurveContract::U256_3Eth(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
295                Ok(x) => Ok(x),
296                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
297            },
298        }
299    }
300
301    pub fn get_dx_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
302        let ret: Result<Bytes, Report> = match self {
303            CurveContract::I128_2To(interface) => Ok(interface.get_dx(i.into(), j.into(), amount).calldata().clone()),
304            CurveContract::U256_3EthTo(interface) => Ok(interface.get_dx(U256::from(i), U256::from(j), amount).calldata().clone()),
305            CurveContract::U256_3EthTo2(interface) => Ok(interface.get_dx(U256::from(i), U256::from(j), amount).calldata().clone()),
306            _ => Err(eyre!("CURVE_CANNOT_CALC_DX")),
307        };
308        ret
309    }
310
311    pub fn get_dy_underlying_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
312        match self {
313            CurveContract::I128_2ToMeta(interface) => Ok(interface.get_dy_underlying(i.into(), j.into(), amount).calldata().clone()),
314            _ => Err(eyre!("GET_DY_UNDERLYING_NOT_SUPPORTED")),
315        }
316    }
317
318    pub fn get_dy_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
319        match self {
320            CurveContract::I128_2(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
321            CurveContract::I128_2ToMeta(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
322
323            CurveContract::I128_2To(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
324            CurveContract::I128_3(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
325            CurveContract::I128_4(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
326            CurveContract::U256_2(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
327            CurveContract::U256_2To(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
328            CurveContract::U256_2EthTo(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
329            CurveContract::U256_3Eth(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
330            CurveContract::U256_3EthTo(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
331            CurveContract::U256_3EthTo2(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
332        }
333    }
334
335    pub fn calc_token_amount_call_data(&self, i: u32, amount: U256) -> Result<Bytes> {
336        match self {
337            CurveContract::I128_2(interface) => {
338                let mut amounts: [U256; 2] = Default::default();
339                amounts[i as usize] = amount;
340                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
341            }
342            CurveContract::I128_3(interface) => {
343                let mut amounts: [U256; 3] = Default::default();
344                amounts[i as usize] = amount;
345                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
346            }
347            CurveContract::I128_4(interface) => {
348                let mut amounts: [U256; 4] = Default::default();
349                amounts[i as usize] = amount;
350                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
351            }
352            _ => Err(eyre!("CURVE_TOKEN_AMOUNT_CALL_DATA_NOT_SUPPORTED")),
353        }
354    }
355
356    pub fn calc_withdraw_one_coin_call_data(&self, i: u32, amount: U256) -> Result<Bytes> {
357        match self {
358            CurveContract::I128_3(interface) => Ok(interface.calc_withdraw_one_coin(amount, i.into()).calldata().clone()),
359            _ => Err(eyre!("CURVE_WITHDRAW_ONE_COIN_NOT_SUPPORTED")),
360        }
361    }
362
363    pub fn get_exchange_underlying_call_data(&self, i: u32, j: u32, amount: U256, min_dy: U256, to: Address) -> Result<Bytes> {
364        match self {
365            CurveContract::I128_2ToMeta(interface) => {
366                Ok(interface.exchange_underlying(i.into(), j.into(), amount, min_dy, to).calldata().clone())
367            }
368            _ => Err(eyre!("GET_EXCHANGE_UNDERLYING_CALL_DATA_NOT_SUPPORTED")),
369        }
370    }
371
372    pub fn get_exchange_call_data(&self, i: u32, j: u32, amount: U256, min_dy: U256, to: Address) -> Result<Bytes> {
373        match self {
374            CurveContract::I128_2(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
375            CurveContract::I128_2ToMeta(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy, to).calldata().clone()),
376            CurveContract::I128_2To(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy, to).calldata().clone()),
377            CurveContract::I128_3(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
378            CurveContract::I128_4(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
379            CurveContract::U256_2(interface) => Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy).calldata().clone()),
380            CurveContract::U256_2To(interface) => {
381                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, to).calldata().clone())
382            }
383            CurveContract::U256_2EthTo(interface) => {
384                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
385            }
386            CurveContract::U256_3Eth(interface) => {
387                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false).calldata().clone())
388            }
389            CurveContract::U256_3EthTo(interface) => {
390                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
391            }
392            CurveContract::U256_3EthTo2(interface) => {
393                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
394            }
395        }
396    }
397
398    pub fn get_add_liquidity_call_data(&self, i: u32, amount: U256, _to: Address) -> Result<Bytes> {
399        match self {
400            CurveContract::I128_3(interface) => {
401                let mut amounts: [U256; 3] = Default::default();
402                amounts[i as usize] = amount;
403                Ok(interface.add_liquidity(amounts, U256::ZERO).calldata().clone())
404            }
405            _ => Err(eyre!("ADD_LIQUIDITY_NOT_SUPPORTED")),
406        }
407    }
408
409    pub fn get_remove_liquidity_one_coin_call_data(&self, i: u32, amount: U256, _to: Address) -> Result<Bytes> {
410        match self {
411            CurveContract::I128_3(interface) => Ok(interface.remove_liquidity_one_coin(amount, i as i128, U256::ZERO).calldata().clone()),
412            _ => Err(eyre!("REMOVE_LIQUIDITY_ONE_COIN_NOT_SUPPORTED")),
413        }
414    }
415}
416
417pub struct CurveProtocol<P, N>
418where
419    N: Network,
420    P: Provider<N> + Send + Sync + Clone + 'static,
421{
422    p: PhantomData<(P, N)>,
423}
424
425impl<P, N> CurveProtocol<P, N>
426where
427    N: Network,
428    P: Provider<N> + Send + Sync + Clone + 'static,
429{
430    pub fn get_underlying_tokens(meta_token_address: Address) -> Result<Vec<Address>> {
431        if meta_token_address == address!("6c3F90f043a72FA612cbac8115EE7e52BDe6E490") {
432            Ok(vec![
433                address!("6B175474E89094C44Da98b954EedeAC495271d0F"),
434                address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
435                address!("dAC17F958D2ee523a2206206994597C13D831ec7"),
436            ])
437        } else if meta_token_address == address!("3175Df0976dFA876431C2E9eE6Bc45b65d3473CC") {
438            Ok(vec![address!("853d955aCEf822Db058eb8505911ED77F175b99e"), address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")])
439        } else {
440            Err(eyre!("META_POOL_NOT_FOUND"))
441        }
442    }
443
444    pub fn new_i128_2(client: P, address: Address) -> CurveContract<P, N> {
445        let contract = ICurveI128_2Instance::new(address, client);
446        CurveContract::I128_2(contract)
447    }
448
449    pub fn new_i128_2_to_meta(client: P, address: Address) -> CurveContract<P, N> {
450        let contract = ICurveI128_2_To_MetaInstance::new(address, client);
451        CurveContract::I128_2ToMeta(contract)
452    }
453
454    pub fn new_i128_2_to(client: P, address: Address) -> CurveContract<P, N> {
455        let contract = ICurveI128_2_To::new(address, client);
456        CurveContract::I128_2To(contract)
457    }
458    pub fn new_i128_3(client: P, address: Address) -> CurveContract<P, N> {
459        let contract = ICurveI128_3::new(address, client);
460        CurveContract::I128_3(contract)
461    }
462    pub fn new_i128_4(client: P, address: Address) -> CurveContract<P, N> {
463        let contract = ICurveI128_4::new(address, client);
464        CurveContract::I128_4(contract)
465    }
466    pub fn new_u256_2(client: P, address: Address) -> CurveContract<P, N> {
467        let contract = ICurveU256_2::new(address, client);
468        CurveContract::U256_2(contract)
469    }
470
471    pub fn new_u256_2_to(client: P, address: Address) -> CurveContract<P, N> {
472        let contract = ICurveU256_2_To::new(address, client);
473        CurveContract::U256_2To(contract)
474    }
475
476    pub fn new_u256_2_eth_to(client: P, address: Address) -> CurveContract<P, N> {
477        let contract = ICurveU256_2_Eth_To::new(address, client);
478        CurveContract::U256_2EthTo(contract)
479    }
480
481    pub fn new_u256_3_eth_to(client: P, address: Address) -> CurveContract<P, N> {
482        let contract = ICurveU256_3_Eth_To::new(address, client);
483        CurveContract::U256_3EthTo(contract)
484    }
485    pub fn new_u256_3_eth_to2(client: P, address: Address) -> CurveContract<P, N> {
486        let contract = ICurveU256_3_Eth_To2::new(address, client);
487        CurveContract::U256_3EthTo2(contract)
488    }
489
490    pub fn new_u256_3_eth(client: P, address: Address) -> CurveContract<P, N> {
491        let contract = ICurveU256_3_Eth::new(address, client);
492        CurveContract::U256_3Eth(contract)
493    }
494
495    /*
496    I128_3
497    0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7 // DAI-USDT-USDC
498
499    I128_2_to
500    0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E // crvUSD-USDC
501
502    U256_2_Eth_to
503    0x9409280DC1e6D33AB7A8C6EC03e5763FB61772B5  // LDO-ETH
504
505    U256_3_Eth
506    0xD51a44d3FaE010294C616388b506AcdA1bfAAE46 // WETH-WBTC-USDT
507
508
509    U256_3_Eth_to
510    0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B // WETH-WBTC-USDC
511    0xf5f5B97624542D72A9E06f04804Bf81baA15e2B4 // WETH-WBTC-USDT
512     */
513
514    fn match_abi(code: &Bytes, abi: Vec<[u8; 4]>) -> bool {
515        //println!("Code len {}", code.len());
516        for f in abi.iter() {
517            if !code.as_ref().windows(4).any(|sig| sig == f) {
518                //println!("{} not found", fn_name);
519                return false;
520            } else {
521                //println!("{} found", fn_name);
522            }
523        }
524
525        true
526    }
527
528    pub async fn get_factory_address(client: P, id: u32) -> Result<Address> {
529        let address_provider_address: Address = "0x0000000022D53366457F9d5E68Ec105046FC4383".parse().unwrap();
530        let address_provider = ICurveAddressProviderInstance::new(address_provider_address, client);
531        match address_provider.get_address(U256::from(id)).call().await {
532            Ok(x) => Ok(x),
533            Err(e) => {
534                error!("Error getting factory address : {}", e);
535                Err(eyre!("GET_FACTORY_ADDRESS_ERROR"))
536            }
537        }
538    }
539
540    pub async fn get_pool_address(client: P, factory_address: Address, pool_id: u32) -> Result<Address> {
541        let factory = ICurveFactoryInstance::new(factory_address, client);
542        match factory.pool_list(U256::from(pool_id)).call().await {
543            Ok(x) => Ok(x),
544            Err(e) => {
545                error!("Error getting factory address :{}", e);
546                Err(eyre!("GET_POOL_ADDRESS_ERROR"))
547            }
548        }
549    }
550
551    pub async fn get_pool_count(client: P, factory_address: Address) -> Result<u32> {
552        let factory = ICurveFactoryInstance::new(factory_address, client);
553        match factory.pool_count().call().await {
554            Ok(x) => Ok(x.to()),
555            Err(e) => {
556                error!("Error getting pool count : {}", e);
557                Err(eyre!("GET_POOL_COUNT_ERROR"))
558            }
559        }
560    }
561
562    pub async fn get_contract_from_code(client: P, address: Address) -> Result<CurveContract<P, N>> {
563        //let sig = ICurveU256_3_EthCalls::Balances(  <ICurveU256_3_Eth<M>>::BalancesCall );
564        //let sig = ICurveU256_3_EthCalls::Balances(  BalancesCall{} );
565
566        let mut code = client.get_code_at(address).block_id(BlockId::Number(BlockNumberOrTag::Latest)).await?;
567
568        if code.len() < 100 {
569            for i in 20..code.len() - 1 {
570                if code[i] == 0x5A && code[i + 1] == 0xF4 {
571                    let underlying_address = Address::from_slice(&code.to_vec()[i - 20..i]);
572                    debug!("get_contract_from_code Underlying address {}", underlying_address);
573                    code = client.get_code_at(underlying_address).block_id(BlockId::Number(BlockNumberOrTag::Latest)).await?;
574                    break;
575                }
576            }
577        }
578
579        let code: Bytes = code;
580
581        if code.len() < 100 {
582            return Err(eyre!("CANNOT_FIND_UNDERLYING"));
583        }
584
585        if Self::match_abi(&code, ICurveI128_2_To_Meta::ICurveI128_2_To_MetaCalls::selectors().collect()) {
586            return Ok(Self::new_i128_2_to_meta(client, address));
587        }
588
589        if Self::match_abi(&code, ICurveI128_2_ToCalls::selectors().collect()) {
590            return Ok(Self::new_i128_2_to(client, address));
591        }
592
593        if Self::match_abi(&code, ICurveI128_2::ICurveI128_2Calls::selectors().collect()) {
594            return Ok(Self::new_i128_2(client, address));
595        }
596        if Self::match_abi(&code, ICurveI128_3Calls::selectors().collect()) {
597            return Ok(Self::new_i128_3(client, address));
598        }
599        if Self::match_abi(&code, ICurveI128_4Calls::selectors().collect()) {
600            return Ok(Self::new_i128_4(client, address));
601        }
602        if Self::match_abi(&code, ICurveU256_2_ToCalls::selectors().collect()) {
603            return Ok(Self::new_u256_2_to(client, address));
604        }
605        if Self::match_abi(&code, ICurveU256_2Calls::selectors().collect()) {
606            return Ok(Self::new_u256_2(client, address));
607        }
608        if Self::match_abi(&code, ICurveU256_2_Eth_ToCalls::selectors().collect()) {
609            return Ok(Self::new_u256_2_eth_to(client, address));
610        }
611        if Self::match_abi(&code, ICurveU256_3_EthCalls::selectors().collect()) {
612            return Ok(Self::new_u256_3_eth(client, address));
613        }
614        if Self::match_abi(&code, ICurveU256_3_Eth_ToCalls::selectors().collect()) {
615            return Ok(Self::new_u256_3_eth_to(client, address));
616        }
617        if Self::match_abi(&code, ICurveU256_3_Eth_To2Calls::selectors().collect()) {
618            return Ok(Self::new_u256_3_eth_to2(client, address));
619        }
620
621        Err(eyre!("ABI_NOT_FOUND"))
622    }
623
624    pub fn get_contracts_vec(client: P) -> Vec<CurveContract<P, N>> {
625        vec![
626            Self::new_u256_3_eth_to(client.clone(), address!("f5f5B97624542D72A9E06f04804Bf81baA15e2B4")),
627            //Self::new_u256_3_eth_to(client.clone(), "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490".parse().unwrap()),
628            Self::new_i128_3(client.clone(), address!("bEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")),
629            Self::new_i128_2_to(client.clone(), address!("4DEcE678ceceb27446b35C672dC7d61F30bAD69E")),
630            Self::new_u256_2_eth_to(client.clone(), address!("9409280DC1e6D33AB7A8C6EC03e5763FB61772B5")),
631            Self::new_u256_3_eth(client.clone(), address!("D51a44d3FaE010294C616388b506AcdA1bfAAE46")),
632            Self::new_u256_3_eth_to(client.clone(), address!("7F86Bf177Dd4F3494b841a37e810A34dD56c829B")),
633            Self::new_i128_2(client.clone(), address!("DC24316b9AE028F1497c275EB9192a3Ea0f67022")),
634            Self::new_i128_2_to(client.clone(), address!("828b154032950C8ff7CF8085D841723Db2696056")),
635            //Self::new_i128_2_to_meta(client.clone(), address!("Ed279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA".parse().unwrap()),
636        ]
637    }
638}