kabu_defi_pools/protocols/
curve.rs

1use std::fmt::{Display, Formatter};
2use std::marker::PhantomData;
3
4use alloy::primitives::{Address, Bytes, U256, address};
5use alloy::providers::{Network, Provider};
6use alloy::rpc::types::{BlockId, BlockNumberOrTag};
7use alloy::sol_types::SolInterface;
8use eyre::{Report, Result, eyre};
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 { Self::balance128(client, address, coin_id).await } else { Err(eyre!("CANNOT_GET_COIN_BALANCE")) }
156            }
157        }
158    }
159    pub async fn coins(client: P, address: Address) -> Result<Vec<Address>> {
160        let mut ret: Vec<Address> = Vec::new();
161        for i in 0..4 {
162            match Self::coin(client.clone(), address, i).await {
163                Ok(coin_address) => ret.push(coin_address),
164                Err(_) => break,
165            }
166        }
167        if ret.is_empty() {
168            trace!("coin fetch coins");
169            Err(eyre!("CANNOT_GET_COIN_ADDRESS"))
170        } else {
171            trace!("coins @{} {:?}", address, ret);
172            Ok(ret)
173        }
174    }
175
176    pub async fn balances(client: P, address: Address) -> Result<Vec<U256>> {
177        let mut ret: Vec<U256> = Vec::new();
178
179        let common_contract = ICurveCommonInstance::new(address, client.clone());
180        match common_contract.get_balances().call().await {
181            Ok(return_bytes) => {
182                if return_bytes.0.len() < 64 {
183                    return Err(eyre!("CANNOT_FETCH_BALANCES"));
184                }
185                let balances_count = U256::from_be_slice(&return_bytes.0.to_vec()[0..32]);
186                for i in 0usize..balances_count.to() {
187                    let balance = U256::from_be_slice(&return_bytes.0.to_vec()[32 + i * 32..64 + i * 32]);
188                    ret.push(balance)
189                }
190                debug!("Curve Balances {:?} {:?}", address, ret);
191                Ok(ret)
192            }
193            Err(e) => {
194                for i in 0..4 {
195                    match Self::balance(client.clone(), address, i).await {
196                        Ok(balance) => ret.push(balance),
197                        Err(e) => {
198                            trace!("Error fetching coin balance {} : {}", i, e);
199                            break;
200                        }
201                    }
202                }
203                if ret.is_empty() {
204                    trace!("coin call error {}", e);
205                    Err(eyre!("CANNOT_GET_COIN_BALANCE"))
206                } else {
207                    Ok(ret)
208                }
209            }
210        }
211    }
212}
213
214impl<P, N> CurveContract<P, N>
215where
216    N: Network,
217    P: Provider<N> + Send + Sync + Clone + 'static,
218{
219    pub fn get_address(&self) -> Address {
220        match self {
221            CurveContract::I128_2(interface) => *interface.address(),
222
223            CurveContract::I128_2ToMeta(interface) => *interface.address(),
224
225            CurveContract::I128_2To(interface) => *interface.address(),
226            CurveContract::I128_3(interface) => *interface.address(),
227            CurveContract::I128_4(interface) => *interface.address(),
228            CurveContract::U256_2(interface) => *interface.address(),
229            CurveContract::U256_2To(interface) => *interface.address(),
230            CurveContract::U256_2EthTo(interface) => *interface.address(),
231            CurveContract::U256_3Eth(interface) => *interface.address(),
232            CurveContract::U256_3EthTo(interface) => *interface.address(),
233            CurveContract::U256_3EthTo2(interface) => *interface.address(),
234        }
235    }
236
237    pub fn can_exchange_to(&self) -> bool {
238        !(matches!(self, CurveContract::I128_3(_)) | matches!(self, CurveContract::U256_3Eth(_)))
239    }
240
241    pub fn can_calculate_in_amount(&self) -> bool {
242        matches!(
243            self,
244            CurveContract::I128_2To(_) | CurveContract::U256_2EthTo(_) | CurveContract::U256_3EthTo(_) | CurveContract::I128_2ToMeta(_)
245        )
246    }
247
248    pub async fn get_dy(&self, i: u32, j: u32, amount: U256) -> Result<U256> {
249        match self {
250            CurveContract::I128_2(interface) => match interface.get_dy(i.into(), j.into(), amount).call().await {
251                Ok(x) => Ok(x),
252                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
253            },
254            CurveContract::I128_2ToMeta(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_2To(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_3(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_4(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::U256_2(interface) => match interface.get_dy(U256::from(i), U256::from(j), amount).call().await {
271                Ok(x) => Ok(x),
272                _ => Err(eyre!("CURVE_GET_DY_CALL_ERROR")),
273            },
274            CurveContract::U256_2To(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_2EthTo(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_3EthTo(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_3EthTo2(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_3Eth(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        }
295    }
296
297    pub fn get_dx_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
298        let ret: Result<Bytes, Report> = match self {
299            CurveContract::I128_2To(interface) => Ok(interface.get_dx(i.into(), j.into(), amount).calldata().clone()),
300            CurveContract::U256_3EthTo(interface) => Ok(interface.get_dx(U256::from(i), U256::from(j), amount).calldata().clone()),
301            CurveContract::U256_3EthTo2(interface) => Ok(interface.get_dx(U256::from(i), U256::from(j), amount).calldata().clone()),
302            _ => Err(eyre!("CURVE_CANNOT_CALC_DX")),
303        };
304        ret
305    }
306
307    pub fn get_dy_underlying_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
308        match self {
309            CurveContract::I128_2ToMeta(interface) => Ok(interface.get_dy_underlying(i.into(), j.into(), amount).calldata().clone()),
310            _ => Err(eyre!("GET_DY_UNDERLYING_NOT_SUPPORTED")),
311        }
312    }
313
314    pub fn get_dy_call_data(&self, i: u32, j: u32, amount: U256) -> Result<Bytes> {
315        match self {
316            CurveContract::I128_2(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
317            CurveContract::I128_2ToMeta(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
318
319            CurveContract::I128_2To(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
320            CurveContract::I128_3(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
321            CurveContract::I128_4(interface) => Ok(interface.get_dy(i.into(), j.into(), amount).calldata().clone()),
322            CurveContract::U256_2(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
323            CurveContract::U256_2To(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
324            CurveContract::U256_2EthTo(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
325            CurveContract::U256_3Eth(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
326            CurveContract::U256_3EthTo(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
327            CurveContract::U256_3EthTo2(interface) => Ok(interface.get_dy(U256::from(i), U256::from(j), amount).calldata().clone()),
328        }
329    }
330
331    pub fn calc_token_amount_call_data(&self, i: u32, amount: U256) -> Result<Bytes> {
332        match self {
333            CurveContract::I128_2(interface) => {
334                let mut amounts: [U256; 2] = Default::default();
335                amounts[i as usize] = amount;
336                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
337            }
338            CurveContract::I128_3(interface) => {
339                let mut amounts: [U256; 3] = Default::default();
340                amounts[i as usize] = amount;
341                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
342            }
343            CurveContract::I128_4(interface) => {
344                let mut amounts: [U256; 4] = Default::default();
345                amounts[i as usize] = amount;
346                Ok(interface.calc_token_amount(amounts, true).calldata().clone())
347            }
348            _ => Err(eyre!("CURVE_TOKEN_AMOUNT_CALL_DATA_NOT_SUPPORTED")),
349        }
350    }
351
352    pub fn calc_withdraw_one_coin_call_data(&self, i: u32, amount: U256) -> Result<Bytes> {
353        match self {
354            CurveContract::I128_3(interface) => Ok(interface.calc_withdraw_one_coin(amount, i.into()).calldata().clone()),
355            _ => Err(eyre!("CURVE_WITHDRAW_ONE_COIN_NOT_SUPPORTED")),
356        }
357    }
358
359    pub fn get_exchange_underlying_call_data(&self, i: u32, j: u32, amount: U256, min_dy: U256, to: Address) -> Result<Bytes> {
360        match self {
361            CurveContract::I128_2ToMeta(interface) => {
362                Ok(interface.exchange_underlying(i.into(), j.into(), amount, min_dy, to).calldata().clone())
363            }
364            _ => Err(eyre!("GET_EXCHANGE_UNDERLYING_CALL_DATA_NOT_SUPPORTED")),
365        }
366    }
367
368    pub fn get_exchange_call_data(&self, i: u32, j: u32, amount: U256, min_dy: U256, to: Address) -> Result<Bytes> {
369        match self {
370            CurveContract::I128_2(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
371            CurveContract::I128_2ToMeta(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy, to).calldata().clone()),
372            CurveContract::I128_2To(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy, to).calldata().clone()),
373            CurveContract::I128_3(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
374            CurveContract::I128_4(interface) => Ok(interface.exchange(i.into(), j.into(), amount, min_dy).calldata().clone()),
375            CurveContract::U256_2(interface) => Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy).calldata().clone()),
376            CurveContract::U256_2To(interface) => {
377                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, to).calldata().clone())
378            }
379            CurveContract::U256_2EthTo(interface) => {
380                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
381            }
382            CurveContract::U256_3Eth(interface) => {
383                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false).calldata().clone())
384            }
385            CurveContract::U256_3EthTo(interface) => {
386                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
387            }
388            CurveContract::U256_3EthTo2(interface) => {
389                Ok(interface.exchange(U256::from(i), U256::from(j), amount, min_dy, false, to).calldata().clone())
390            }
391        }
392    }
393
394    pub fn get_add_liquidity_call_data(&self, i: u32, amount: U256, _to: Address) -> Result<Bytes> {
395        match self {
396            CurveContract::I128_3(interface) => {
397                let mut amounts: [U256; 3] = Default::default();
398                amounts[i as usize] = amount;
399                Ok(interface.add_liquidity(amounts, U256::ZERO).calldata().clone())
400            }
401            _ => Err(eyre!("ADD_LIQUIDITY_NOT_SUPPORTED")),
402        }
403    }
404
405    pub fn get_remove_liquidity_one_coin_call_data(&self, i: u32, amount: U256, _to: Address) -> Result<Bytes> {
406        match self {
407            CurveContract::I128_3(interface) => Ok(interface.remove_liquidity_one_coin(amount, i as i128, U256::ZERO).calldata().clone()),
408            _ => Err(eyre!("REMOVE_LIQUIDITY_ONE_COIN_NOT_SUPPORTED")),
409        }
410    }
411}
412
413pub struct CurveProtocol<P, N>
414where
415    N: Network,
416    P: Provider<N> + Send + Sync + Clone + 'static,
417{
418    p: PhantomData<(P, N)>,
419}
420
421impl<P, N> CurveProtocol<P, N>
422where
423    N: Network,
424    P: Provider<N> + Send + Sync + Clone + 'static,
425{
426    pub fn get_underlying_tokens(meta_token_address: Address) -> Result<Vec<Address>> {
427        if meta_token_address == address!("6c3F90f043a72FA612cbac8115EE7e52BDe6E490") {
428            Ok(vec![
429                address!("6B175474E89094C44Da98b954EedeAC495271d0F"),
430                address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
431                address!("dAC17F958D2ee523a2206206994597C13D831ec7"),
432            ])
433        } else if meta_token_address == address!("3175Df0976dFA876431C2E9eE6Bc45b65d3473CC") {
434            Ok(vec![address!("853d955aCEf822Db058eb8505911ED77F175b99e"), address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")])
435        } else {
436            Err(eyre!("META_POOL_NOT_FOUND"))
437        }
438    }
439
440    pub fn new_i128_2(client: P, address: Address) -> CurveContract<P, N> {
441        let contract = ICurveI128_2Instance::new(address, client);
442        CurveContract::I128_2(contract)
443    }
444
445    pub fn new_i128_2_to_meta(client: P, address: Address) -> CurveContract<P, N> {
446        let contract = ICurveI128_2_To_MetaInstance::new(address, client);
447        CurveContract::I128_2ToMeta(contract)
448    }
449
450    pub fn new_i128_2_to(client: P, address: Address) -> CurveContract<P, N> {
451        let contract = ICurveI128_2_To::new(address, client);
452        CurveContract::I128_2To(contract)
453    }
454    pub fn new_i128_3(client: P, address: Address) -> CurveContract<P, N> {
455        let contract = ICurveI128_3::new(address, client);
456        CurveContract::I128_3(contract)
457    }
458    pub fn new_i128_4(client: P, address: Address) -> CurveContract<P, N> {
459        let contract = ICurveI128_4::new(address, client);
460        CurveContract::I128_4(contract)
461    }
462    pub fn new_u256_2(client: P, address: Address) -> CurveContract<P, N> {
463        let contract = ICurveU256_2::new(address, client);
464        CurveContract::U256_2(contract)
465    }
466
467    pub fn new_u256_2_to(client: P, address: Address) -> CurveContract<P, N> {
468        let contract = ICurveU256_2_To::new(address, client);
469        CurveContract::U256_2To(contract)
470    }
471
472    pub fn new_u256_2_eth_to(client: P, address: Address) -> CurveContract<P, N> {
473        let contract = ICurveU256_2_Eth_To::new(address, client);
474        CurveContract::U256_2EthTo(contract)
475    }
476
477    pub fn new_u256_3_eth_to(client: P, address: Address) -> CurveContract<P, N> {
478        let contract = ICurveU256_3_Eth_To::new(address, client);
479        CurveContract::U256_3EthTo(contract)
480    }
481    pub fn new_u256_3_eth_to2(client: P, address: Address) -> CurveContract<P, N> {
482        let contract = ICurveU256_3_Eth_To2::new(address, client);
483        CurveContract::U256_3EthTo2(contract)
484    }
485
486    pub fn new_u256_3_eth(client: P, address: Address) -> CurveContract<P, N> {
487        let contract = ICurveU256_3_Eth::new(address, client);
488        CurveContract::U256_3Eth(contract)
489    }
490
491    /*
492    I128_3
493    0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7 // DAI-USDT-USDC
494
495    I128_2_to
496    0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E // crvUSD-USDC
497
498    U256_2_Eth_to
499    0x9409280DC1e6D33AB7A8C6EC03e5763FB61772B5  // LDO-ETH
500
501    U256_3_Eth
502    0xD51a44d3FaE010294C616388b506AcdA1bfAAE46 // WETH-WBTC-USDT
503
504
505    U256_3_Eth_to
506    0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B // WETH-WBTC-USDC
507    0xf5f5B97624542D72A9E06f04804Bf81baA15e2B4 // WETH-WBTC-USDT
508     */
509
510    fn match_abi(code: &Bytes, abi: Vec<[u8; 4]>) -> bool {
511        //println!("Code len {}", code.len());
512        for f in abi.iter() {
513            if !code.as_ref().windows(4).any(|sig| sig == f) {
514                //println!("{} not found", fn_name);
515                return false;
516            } else {
517                //println!("{} found", fn_name);
518            }
519        }
520
521        true
522    }
523
524    pub async fn get_factory_address(client: P, id: u32) -> Result<Address> {
525        let address_provider_address: Address = "0x0000000022D53366457F9d5E68Ec105046FC4383".parse().unwrap();
526        let address_provider = ICurveAddressProviderInstance::new(address_provider_address, client);
527        match address_provider.get_address(U256::from(id)).call().await {
528            Ok(x) => Ok(x),
529            Err(e) => {
530                error!("Error getting factory address : {}", e);
531                Err(eyre!("GET_FACTORY_ADDRESS_ERROR"))
532            }
533        }
534    }
535
536    pub async fn get_pool_address(client: P, factory_address: Address, pool_id: u32) -> Result<Address> {
537        let factory = ICurveFactoryInstance::new(factory_address, client);
538        match factory.pool_list(U256::from(pool_id)).call().await {
539            Ok(x) => Ok(x),
540            Err(e) => {
541                error!("Error getting factory address :{}", e);
542                Err(eyre!("GET_POOL_ADDRESS_ERROR"))
543            }
544        }
545    }
546
547    pub async fn get_pool_count(client: P, factory_address: Address) -> Result<u32> {
548        let factory = ICurveFactoryInstance::new(factory_address, client);
549        match factory.pool_count().call().await {
550            Ok(x) => Ok(x.to()),
551            Err(e) => {
552                error!("Error getting pool count : {}", e);
553                Err(eyre!("GET_POOL_COUNT_ERROR"))
554            }
555        }
556    }
557
558    pub async fn get_contract_from_code(client: P, address: Address) -> Result<CurveContract<P, N>> {
559        //let sig = ICurveU256_3_EthCalls::Balances(  <ICurveU256_3_Eth<M>>::BalancesCall );
560        //let sig = ICurveU256_3_EthCalls::Balances(  BalancesCall{} );
561
562        let mut code = client.get_code_at(address).block_id(BlockId::Number(BlockNumberOrTag::Latest)).await?;
563
564        if code.len() < 100 {
565            for i in 20..code.len() - 1 {
566                if code[i] == 0x5A && code[i + 1] == 0xF4 {
567                    let underlying_address = Address::from_slice(&code.to_vec()[i - 20..i]);
568                    debug!("get_contract_from_code Underlying address {}", underlying_address);
569                    code = client.get_code_at(underlying_address).block_id(BlockId::Number(BlockNumberOrTag::Latest)).await?;
570                    break;
571                }
572            }
573        }
574
575        let code: Bytes = code;
576
577        if code.len() < 100 {
578            return Err(eyre!("CANNOT_FIND_UNDERLYING"));
579        }
580
581        if Self::match_abi(&code, ICurveI128_2_To_Meta::ICurveI128_2_To_MetaCalls::selectors().collect()) {
582            return Ok(Self::new_i128_2_to_meta(client, address));
583        }
584
585        if Self::match_abi(&code, ICurveI128_2_ToCalls::selectors().collect()) {
586            return Ok(Self::new_i128_2_to(client, address));
587        }
588
589        if Self::match_abi(&code, ICurveI128_2::ICurveI128_2Calls::selectors().collect()) {
590            return Ok(Self::new_i128_2(client, address));
591        }
592        if Self::match_abi(&code, ICurveI128_3Calls::selectors().collect()) {
593            return Ok(Self::new_i128_3(client, address));
594        }
595        if Self::match_abi(&code, ICurveI128_4Calls::selectors().collect()) {
596            return Ok(Self::new_i128_4(client, address));
597        }
598        if Self::match_abi(&code, ICurveU256_2_ToCalls::selectors().collect()) {
599            return Ok(Self::new_u256_2_to(client, address));
600        }
601        if Self::match_abi(&code, ICurveU256_2Calls::selectors().collect()) {
602            return Ok(Self::new_u256_2(client, address));
603        }
604        if Self::match_abi(&code, ICurveU256_2_Eth_ToCalls::selectors().collect()) {
605            return Ok(Self::new_u256_2_eth_to(client, address));
606        }
607        if Self::match_abi(&code, ICurveU256_3_EthCalls::selectors().collect()) {
608            return Ok(Self::new_u256_3_eth(client, address));
609        }
610        if Self::match_abi(&code, ICurveU256_3_Eth_ToCalls::selectors().collect()) {
611            return Ok(Self::new_u256_3_eth_to(client, address));
612        }
613        if Self::match_abi(&code, ICurveU256_3_Eth_To2Calls::selectors().collect()) {
614            return Ok(Self::new_u256_3_eth_to2(client, address));
615        }
616
617        Err(eyre!("ABI_NOT_FOUND"))
618    }
619
620    pub fn get_contracts_vec(client: P) -> Vec<CurveContract<P, N>> {
621        vec![
622            Self::new_u256_3_eth_to(client.clone(), address!("f5f5B97624542D72A9E06f04804Bf81baA15e2B4")),
623            //Self::new_u256_3_eth_to(client.clone(), "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490".parse().unwrap()),
624            Self::new_i128_3(client.clone(), address!("bEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")),
625            Self::new_i128_2_to(client.clone(), address!("4DEcE678ceceb27446b35C672dC7d61F30bAD69E")),
626            Self::new_u256_2_eth_to(client.clone(), address!("9409280DC1e6D33AB7A8C6EC03e5763FB61772B5")),
627            Self::new_u256_3_eth(client.clone(), address!("D51a44d3FaE010294C616388b506AcdA1bfAAE46")),
628            Self::new_u256_3_eth_to(client.clone(), address!("7F86Bf177Dd4F3494b841a37e810A34dD56c829B")),
629            Self::new_i128_2(client.clone(), address!("DC24316b9AE028F1497c275EB9192a3Ea0f67022")),
630            Self::new_i128_2_to(client.clone(), address!("828b154032950C8ff7CF8085D841723Db2696056")),
631            //Self::new_i128_2_to_meta(client.clone(), address!("Ed279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA".parse().unwrap()),
632        ]
633    }
634}