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 };
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 fn match_abi(code: &Bytes, abi: Vec<[u8; 4]>) -> bool {
515 for f in abi.iter() {
517 if !code.as_ref().windows(4).any(|sig| sig == f) {
518 return false;
520 } else {
521 }
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 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_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 ]
637 }
638}