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 };
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 fn match_abi(code: &Bytes, abi: Vec<[u8; 4]>) -> bool {
511 for f in abi.iter() {
513 if !code.as_ref().windows(4).any(|sig| sig == f) {
514 return false;
516 } else {
517 }
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 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_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 ]
633 }
634}