From 4d528ddab3209744039b8745a91cd3bffbbcc076 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:40:26 +0200 Subject: [PATCH 01/13] fix(curve): fix curve tests after SDKv2 update, also add a few missing tests --- .../integration_test.tycho.yaml | 125 +++++--- substreams/ethereum-curve/src/modules.rs | 58 +++- .../ethereum-curve/src/pool_factories.rs | 271 +++++++++++++++--- substreams/ethereum-curve/substreams.yaml | 9 + 4 files changed, 383 insertions(+), 80 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index 6552c25..fdb4361 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -1,9 +1,11 @@ substreams_yaml_path: ./substreams.yaml protocol_type_names: - "curve_pool" -adapter_contract: "CurveSwapAdapter.evm.runtime" -skip_balance_check: false +adapter_contract: "CurveAdapter" +skip_balance_check: true +initialized_accounts: tests: + - name: test_3pool_creation start_block: 10809470 stop_block: 10810226 @@ -16,6 +18,8 @@ tests: - "0x6b175474e89094c44da98b954eedeac495271d0f" static_attributes: creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6" + skip_simulation: false + - name: test_steth_creation start_block: 11592550 stop_block: 11595553 @@ -27,31 +31,46 @@ tests: - "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" static_attributes: creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" + skip_simulation: false + - name: test_crypto_swap_ng_factory_plain_pool_creation - start_block: 19355220 - stop_block: 19356225 + start_block: 18580701 + stop_block: 18614742 + initialized_accounts: + - "0x6a8cbed756804b16e05e741edabd5cb544ae21bf" + - "0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963" # Needed by another component that is created within this block range + - "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" expected_state: protocol_components: - - id: "0xeeda34a377dd0ca676b9511ee1324974fa8d980d" + - id: "0x02950460E2b9529D0E00284A5fA2d7bDF3fA4d72" tokens: - - "0xd9a442856c234a39a81a089c06451ebaa4306a72" - - "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0" + - "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" + - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" static_attributes: - creation_tx: "0x0e2bad5695d4ff8ebbaf668674a24bdcc4843da44933d947f2a454fd731da3c1" + creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" + skip_simulation: false + - name: test_crypto_swap_ng_factory_meta_pool_creation start_block: 19216042 stop_block: 19217045 + initialized_accounts: + - "0x6a8cbed756804b16e05e741edabd5cb544ae21bf" # Factory, needed for implementations contrats queries + - "0xa5588f7cdf560811710a2d82d3c9c99769db1dcb" # Base pool of this meta pool expected_state: protocol_components: - id: "0xef484de8C07B6e2d732A92B5F78e81B38f99f95E" tokens: - "0x865377367054516e17014CcdED1e7d814EDC9ce4" - - "0xA5588F7cdf560811710A2D82D3C9c99769DB1Dcb" + - "0xa5588f7cdf560811710a2d82d3c9c99769db1dcb" static_attributes: creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" + skip_simulation: true # Reason: this pool use a base pool which is also one of its tokens, therefore our token override doesn't work here and it fails on transfers + - name: test_metapool_factory_metapool_creation - start_block: 18028600 + start_block: 18028604 stop_block: 18029610 + initialized_accounts: + - "0xdcef968d416a41cdac0ed8702fac8128a64241a2" expected_state: protocol_components: - id: "0x61fA2c947e523F9ABfb8d7e2903A5D5218C119a7" @@ -60,6 +79,8 @@ tests: - "0x3175Df0976dFA876431C2E9eE6Bc45b65d3473CC" static_attributes: creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" + skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply + - name: test_metapool_factory_plainpool_creation start_block: 18808555 stop_block: 18818577 @@ -71,12 +92,15 @@ tests: - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" static_attributes: creation_tx: "0xeb34c90d352f18ffcfe78b7e393e155f0314acf06c54d1ac9996e4ee5a9b4742" + skip_simulation: false - id: "0x3f67dc2AdBA4B1beB6A48c30AB3AFb1c1440d35B" tokens: - "0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67" - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" static_attributes: creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" + skip_simulation: true # Reason: this pool has no liquidity at stop_block + - name: test_cryptopool_factory_creation start_block: 19162590 stop_block: 19163633 @@ -88,15 +112,20 @@ tests: - "0x4591dbff62656e7859afe5e45f6f47d3669fbb28" static_attributes: creation_tx: "0xa89c09a7e0dfd84f3a294b8df4f33cc4a623e6d52deee357457afe2591ea596f" + skip_simulation: false - id: "0x6c9Fe53cC13b125d6476E5Ce2b76983bd5b7A112" tokens: - "0x35fA164735182de50811E8e2E824cFb9B6118ac2" - "0xf951E335afb289353dc249e82926178EaC7DEd78" static_attributes: creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" + skip_simulation: true # Reason: this pool has no liquidity at stop_block + - name: test_tricrypto_factory_creation start_block: 17371455 stop_block: 17374457 + initialized_accounts: + - "0x0c0e5f2ff0ff18a3be9b835635039256dc4b4963" expected_state: protocol_components: - id: "0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B" @@ -106,38 +135,62 @@ tests: - "0x0000000000000000000000000000000000000000" static_attributes: creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" + skip_simulation: false + - name: test_twocrypto_factory_creation - start_block: 19760009 - stop_block: 19763634 + start_block: 19692166 + stop_block: 19692232 + initialized_accounts: + - "0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f" # Factory, needed for implementations contracts queries expected_state: protocol_components: - - id: "0x011e998d2d794424de95935d55a6ca81822ecb2b" + - id: "0x77146B0a1d08B6844376dF6d9da99bA7F1b19e71" tokens: - - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + - "0x55C08ca52497e2f1534B59E2917BF524D4765257" + - "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" static_attributes: - creation_tx: "0x412b745a9467aed14f22d2a4cc30651939872d19cee65053f14dd3eb9d488003" - - id: "0x19d2b5ce188ca60790755204691e38102749297b" + creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" + skip_simulation: false + + - name: test_stableswap_factory_plain_pool_creation + start_block: 17258004 + stop_block: 17260023 + expected_state: + protocol_components: + - id: "0x390f3595bCa2Df7d23783dFd126427CCeb997BF4" tokens: - - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" - - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + - "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E" + - "0xdAC17F958D2ee523a2206206994597C13D831ec7" static_attributes: - creation_tx: "0x61118d9903f8344e5971d1e7c781f76e855996408dac979d3a4971cefafa6587" - - id: "0xb3341ca63b6cecf1e1a0d1a99bf0587f4c305652" + creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" + skip_simulation: false + + # - name: test_stableswap_factory_meta_pool_creation + # There was no metapool created from this factory yet. + # TODO: Double check https://etherscan.io/address/0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d#events search events with topic 0x01f31cd2abdeb4e5e10ba500f2db0f937d9e8c735ab04681925441b4ea37eda5. + # Got the topic using: + # from web3 import Web3 + # + # def keccak(event): + # return Web3.keccak(text=event).hex() + # + # plain_pool_deployed = "PlainPoolDeployed(address[4],uint256,uint256,address,address)" + # meta_pool_deployed = "MetaPoolDeployed(address,address,uint256,uint256,address)" + # + # print(keccak(plain_pool_deployed)) + # print(keccak(meta_pool_deployed)) + + - name: test_metapool_factory_old + start_block: 11968730 + stop_block: 12028110 + initialized_accounts: + - "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" # Linked pool of this metapool + expected_state: + protocol_components: + - id: "0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B" tokens: - - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + - "0x853d955aCEf822Db058eb8505911ED77F175b99e" + - "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490" static_attributes: - creation_tx: "0xc69332294313b3a8f260e0d5b6a50f0d83707f715fbd8016c32ca61a39ce7ad5" - - id: "0x99ca0fbaa278cd62e26f0e9b6d167b07d1f0d51b" - tokens: - - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - static_attributes: - creation_tx: "0xf2b0c697161f08384c642297e01b3a35f7ec00dd3871d4237a16ae4bb8a1ca99" - - id: "0xde73e407efc75edbafc5bcd62ebb1e7a9b38ebcd" - tokens: - - "0x0d86883faf4ffd7aeb116390af37746f45b6f378" - - "0x78da5799cf427fee11e9996982f4150ece7a99a7" - static_attributes: - creation_tx: "0xd4ad7efdcc16d797dd3494ba02b377da4127fd5b1bd25089858b66e5a7e456ab" + creation_tx: "0x1f2a0d4e1c1eca594bd7f27f9952480ccda422c3453e0c5074a63aa46a2ed628" + skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index 59f75c9..8c63055 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -5,12 +5,19 @@ use itertools::Itertools; use substreams::{ pb::substreams::StoreDeltas, scalar::BigInt, - store::{StoreAddBigInt, StoreGet, StoreGetString, StoreNew, StoreSet, StoreSetString}, + store::{ + StoreAddBigInt, StoreGet, StoreGetInt64, StoreGetString, StoreNew, StoreSet, StoreSetInt64, + StoreSetString, + }, }; - use substreams_ethereum::pb::eth; -use crate::{pool_changes::emit_eth_deltas, pool_factories, pools::emit_specific_pools}; +use crate::{ + consts::{CRYPTO_SWAP_NG_FACTORY, TRICRYPTO_FACTORY}, + pool_changes::emit_eth_deltas, + pool_factories, + pools::emit_specific_pools, +}; use tycho_substreams::{ balances::{extract_balance_deltas_from_tx, store_balance_changes}, contract::extract_contract_changes, @@ -99,6 +106,43 @@ pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: St }); } +/// Stores contracts required by components, for example LP tokens if they are different from the +/// pool. +/// This is later used to index them with `extract_contract_changes` +#[substreams::handlers::store] +pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, store: StoreSetInt64) { + map.tx_components + .iter() + .flat_map(|tx_components| &tx_components.components) + .for_each(|component| { + // Crypto pool factory creates LP token separated from the pool, we need to index it so we add it to the store if the new protocol component comes from this factory + if component + .static_att + .contains(&Attribute { + name: "pool_type".into(), + value: "crypto_pool".into(), + change: ChangeType::Creation.into(), + }) && + component + .static_att + .contains(&Attribute { + name: "factory_name".into(), + value: "crypto_pool_factory".into(), + change: ChangeType::Creation.into(), + }) + { + let lp_token = component + .static_att + .iter() + .find(|attr| attr.name == "lp_token") + .unwrap() + .value + .clone(); + store.set(0, hex::encode(lp_token), &1); + } + }); +} + /// Since the `PoolBalanceChanged` events administer only deltas, we need to leverage a map and a /// store to be able to tally up final balances for tokens in a pool. #[substreams::handlers::map] @@ -153,6 +197,7 @@ pub fn map_protocol_changes( grouped_components: BlockTransactionProtocolComponents, deltas: BlockBalanceDeltas, components_store: StoreGetString, + non_component_accounts_store: StoreGetInt64, balance_store: StoreDeltas, // Note, this map module is using the `deltas` mode for the store. ) -> Result { // We merge contract changes by transaction (identified by transaction index) making it easy to @@ -242,7 +287,12 @@ pub fn map_protocol_changes( |addr| { components_store .get_last(format!("pool:{0}", hex::encode(addr))) - .is_some() + .is_some() || + non_component_accounts_store + .get_last(hex::encode(addr)) + .is_some() || + addr.eq(&CRYPTO_SWAP_NG_FACTORY) || + addr.eq(&TRICRYPTO_FACTORY) }, &mut transaction_changes, ); diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index cf3c658..4418022 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -1,3 +1,4 @@ +use substreams::hex; use substreams_ethereum::{ pb::eth::v2::{Call, Log, TransactionTrace}, Event, Function, @@ -66,9 +67,9 @@ fn swap_weth_for_eth(tokens: Vec>) -> Vec> { /// The basic flow of this function is as follows: /// - Match the factory address /// - Decode the relevant event from the log -/// - Attempt to decode the cooresponding function call (based on the permutation of the ABI) +/// - Attempt to decode the corresponding function call (based on the permutation of the ABI) /// - Optionally make an RPC call to produce further information (see metapools) -/// - Construct the cooresponding `ProtocolComponent` +/// - Construct the corresponding `ProtocolComponent` pub fn address_map( call_address: &[u8; 20], log: &Log, @@ -84,6 +85,12 @@ pub fn address_map( let component_id = &call.return_data[12..]; + let pool_implementation = abi::crypto_pool_factory::functions::PoolImplementation {} + .call(CRYPTO_POOL_FACTORY.to_vec())?; + + let token_implementation = abi::crypto_pool_factory::functions::TokenImplementation {} + .call(CRYPTO_POOL_FACTORY.to_vec())?; + Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -93,7 +100,7 @@ pub fn address_map( index: tx.index.into(), }), tokens, - contracts: vec![component_id.into()], + contracts: vec![component_id.into(), pool_added.token.clone()], static_att: vec![ Attribute { name: "pool_type".into(), @@ -115,6 +122,21 @@ pub fn address_map( value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), change: ChangeType::Creation.into(), }, + Attribute { + name: "lp_token".into(), + value: pool_added.token, + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&pool_implementation.try_into().unwrap()), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(&token_implementation.try_into().unwrap()), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -164,6 +186,17 @@ pub fn address_map( // The return data of several of these calls contain the actual component id let component_id = &call.return_data[12..]; + let tokens: Vec<_> = pool_added + .coins + .into_iter() + .filter(|token| *token != [0; 20]) + .collect(); + + let pool_implementation = abi::meta_pool_factory::functions::PlainImplementations { + arg0: BigInt::from(tokens.len()), + arg1: add_pool.implementation_idx, + } + .call(META_POOL_FACTORY.to_vec())?; Some(ProtocolComponent { id: hex::encode(component_id), @@ -173,11 +206,7 @@ pub fn address_map( hash: tx.hash.clone(), index: tx.index.into(), }), - tokens: pool_added - .coins - .into_iter() - .filter(|token| *token != [0; 20]) - .collect(), + tokens, contracts: vec![component_id.into()], static_att: vec![ Attribute { @@ -200,6 +229,13 @@ pub fn address_map( value: address_to_bytes_with_0x(&META_POOL_FACTORY), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x( + &pool_implementation.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -238,6 +274,14 @@ pub fn address_map( abi::meta_registry::functions::GetLpToken1 { pool: add_pool.base_pool.clone() }; let lp_token = get_lp_token.call(META_REGISTRY.to_vec())?; + let pool_implementation = + abi::meta_pool_factory::functions::MetapoolImplementations { + base_pool: add_pool.base_pool.clone(), + } + .call(META_POOL_FACTORY.to_vec())? + [usize::try_from(add_pool.implementation_idx.to_u64()).unwrap()] + .clone(); + Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -247,7 +291,7 @@ pub fn address_map( index: tx.index.into(), }), tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], + contracts: vec![component_id.into(), add_pool.base_pool.clone()], static_att: vec![ Attribute { name: "pool_type".into(), @@ -276,6 +320,13 @@ pub fn address_map( ), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x( + &pool_implementation.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -309,6 +360,20 @@ pub fn address_map( call, ) })?; + let filtered: Vec<_> = tx + .calls + .iter() + .filter(|call| !call.account_creations.is_empty()) + .collect(); + + let implementation = extract_eip1167_target_from_code( + filtered + .first()? + .code_changes + .first()? + .new_code + .clone(), + ); let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); @@ -351,6 +416,11 @@ pub fn address_map( ), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&implementation.try_into().unwrap()), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -382,7 +452,7 @@ pub fn address_map( index: tx.index.into(), }), tokens: pool_added.coins, - contracts: vec![component_id.into()], + contracts: vec![component_id.into(), CRYPTO_SWAP_NG_FACTORY.into()], static_att: vec![ Attribute { name: "pool_type".into(), @@ -404,6 +474,16 @@ pub fn address_map( value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:{}:views_implementation()", + format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -430,7 +510,11 @@ pub fn address_map( index: tx.index.into(), }), tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], + contracts: vec![ + component_id.into(), + CRYPTO_SWAP_NG_FACTORY.into(), + pool_added.base_pool.clone(), + ], static_att: vec![ Attribute { name: "pool_type".into(), @@ -459,6 +543,26 @@ pub fn address_map( ), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:{}:views_implementation()", + format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:{}:math_implementation()", + format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -477,6 +581,60 @@ pub fn address_map( abi::tricrypto_factory::events::TricryptoPoolDeployed::match_and_decode(log) { let tokens = swap_weth_for_eth(pool_added.coins.into()); + let mut static_attributes = vec![ + Attribute { + name: "pool_type".into(), + value: "tricrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "tricrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:{}:views_implementation()", + format!("0x{}", hex::encode(TRICRYPTO_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:{}:math_implementation()", + format!("0x{}", hex::encode(TRICRYPTO_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ]; + + // This is relevant only if the contract has ETH + if tokens.contains(Ð_ADDRESS.into()) { + static_attributes.push(Attribute { + name: "stateless_contract_addr_2".into(), + // WETH + value: address_to_bytes_with_0x(&hex!( + "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + )), + change: ChangeType::Creation.into(), + }) + } Some(ProtocolComponent { id: hex::encode(&pool_added.pool), @@ -487,29 +645,8 @@ pub fn address_map( index: tx.index.into(), }), tokens, - contracts: vec![pool_added.pool], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "tricrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "tricrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - ], + contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], + static_att: static_attributes, change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { name: "curve_pool".into(), @@ -558,6 +695,20 @@ pub fn address_map( return None; }; let component_id = &call.return_data[12..]; + + let tokens: Vec<_> = pool_added + .coins + .into_iter() + .filter(|token| *token != [0; 20]) + .collect(); + + let pool_implementation = + abi::stableswap_factory::functions::PlainImplementations { + arg0: BigInt::from(tokens.len()), + arg1: add_pool.implementation_idx, + } + .call(STABLESWAP_FACTORY.to_vec())?; + Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -566,11 +717,7 @@ pub fn address_map( hash: tx.hash.clone(), index: tx.index.into(), }), - tokens: pool_added - .coins - .into_iter() - .filter(|token| *token != [0; 20]) - .collect(), + tokens, contracts: vec![component_id.into()], static_att: vec![ Attribute { @@ -593,6 +740,13 @@ pub fn address_map( value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x( + &pool_implementation.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -694,7 +848,7 @@ pub fn address_map( index: tx.index.into(), }), tokens: pool_added.coins.into(), - contracts: vec![pool_added.pool], + contracts: vec![pool_added.pool, TWOCRYPTO_FACTORY.into()], static_att: vec![ Attribute { name: "pool_type".into(), @@ -716,6 +870,26 @@ pub fn address_map( value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), change: ChangeType::Creation.into(), }, + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:{}:views_implementation()", + format!("0x{}", hex::encode(TWOCRYPTO_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:{}:math_implementation()", + format!("0x{}", hex::encode(TWOCRYPTO_FACTORY)) + ) + .into(), + change: ChangeType::Creation.into(), + }, ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { @@ -769,3 +943,20 @@ fn get_token_from_pool(pool: &Vec) -> Vec { }) .unwrap() } + +//TODO: We can most likely replace many RPC calls above using this function. +fn extract_eip1167_target_from_code(code: Vec) -> [u8; 20] { + let mut target = [0u8; 20]; + + // Depending on the Vyper version, they use different implementation of EIP1167. + // We use the first 10 bytes of the code to make a clear distinction. + match code[0..10] { + [54, 61, 61, 55, 61, 61, 61, 54, 61, 115] => target.copy_from_slice(&code[10..30]), + [54, 96, 0, 96, 0, 55, 97, 16, 0, 96] => target.copy_from_slice(&code[15..35]), + _ => { + panic!("unknown implementation") + } + } + + target +} diff --git a/substreams/ethereum-curve/substreams.yaml b/substreams/ethereum-curve/substreams.yaml index dc1ae65..f46d6c6 100644 --- a/substreams/ethereum-curve/substreams.yaml +++ b/substreams/ethereum-curve/substreams.yaml @@ -35,6 +35,14 @@ modules: inputs: - map: map_components + - name: store_non_component_accounts + kind: store + initialBlock: 11968730 + updatePolicy: set + valueType: int64 + inputs: + - map: map_components + - name: map_relative_balances kind: map initialBlock: 9906598 # An arbitrary block that should change based on your requirements @@ -60,6 +68,7 @@ modules: - map: map_components - map: map_relative_balances - store: store_component_tokens + - store: store_non_component_accounts - store: store_balances mode: deltas # This is the key property that simplifies `BalanceChange` handling output: From 2f0b084cc6b44789ff94eab4146a5d91c443fdf5 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:00:56 +0200 Subject: [PATCH 02/13] refactor(curve): rename tests --- .../integration_test.tycho.yaml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index fdb4361..e985105 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -6,7 +6,7 @@ skip_balance_check: true initialized_accounts: tests: - - name: test_3pool_creation + - name: test_3pool start_block: 10809470 stop_block: 10810226 expected_state: @@ -20,7 +20,7 @@ tests: creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6" skip_simulation: false - - name: test_steth_creation + - name: test_steth start_block: 11592550 stop_block: 11595553 expected_state: @@ -33,7 +33,7 @@ tests: creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" skip_simulation: false - - name: test_crypto_swap_ng_factory_plain_pool_creation + - name: test_crypto_swap_ng_factory_plain_pool start_block: 18580701 stop_block: 18614742 initialized_accounts: @@ -50,7 +50,7 @@ tests: creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" skip_simulation: false - - name: test_crypto_swap_ng_factory_meta_pool_creation + - name: test_crypto_swap_ng_factory_meta_pool start_block: 19216042 stop_block: 19217045 initialized_accounts: @@ -66,7 +66,7 @@ tests: creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" skip_simulation: true # Reason: this pool use a base pool which is also one of its tokens, therefore our token override doesn't work here and it fails on transfers - - name: test_metapool_factory_metapool_creation + - name: test_metapool_factory_metapool start_block: 18028604 stop_block: 18029610 initialized_accounts: @@ -81,7 +81,7 @@ tests: creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply - - name: test_metapool_factory_plainpool_creation + - name: test_metapool_factory_plainpool start_block: 18808555 stop_block: 18818577 expected_state: @@ -101,7 +101,7 @@ tests: creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" skip_simulation: true # Reason: this pool has no liquidity at stop_block - - name: test_cryptopool_factory_creation + - name: test_cryptopool_factory start_block: 19162590 stop_block: 19163633 expected_state: @@ -121,7 +121,7 @@ tests: creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" skip_simulation: true # Reason: this pool has no liquidity at stop_block - - name: test_tricrypto_factory_creation + - name: test_tricrypto_factory start_block: 17371455 stop_block: 17374457 initialized_accounts: @@ -137,7 +137,7 @@ tests: creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" skip_simulation: false - - name: test_twocrypto_factory_creation + - name: test_twocrypto_factory start_block: 19692166 stop_block: 19692232 initialized_accounts: @@ -152,7 +152,7 @@ tests: creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" skip_simulation: false - - name: test_stableswap_factory_plain_pool_creation + - name: test_stableswap_factory_plain_pool start_block: 17258004 stop_block: 17260023 expected_state: @@ -165,7 +165,7 @@ tests: creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" skip_simulation: false - # - name: test_stableswap_factory_meta_pool_creation + # - name: test_stableswap_factory_meta_pool # There was no metapool created from this factory yet. # TODO: Double check https://etherscan.io/address/0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d#events search events with topic 0x01f31cd2abdeb4e5e10ba500f2db0f937d9e8c735ab04681925441b4ea37eda5. # Got the topic using: From a46e1e4a5737d5a28b02cd980c048ffa9c95d1e0 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:12:19 +0200 Subject: [PATCH 03/13] fix(curve): fix sUSD pool --- .../integration_test.tycho.yaml | 44 ++++++++++++++++++- substreams/ethereum-curve/src/consts.rs | 2 + substreams/ethereum-curve/src/modules.rs | 35 ++++++++++----- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index e985105..8ff02ac 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -33,6 +33,48 @@ tests: creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" skip_simulation: false + - name: test_tricrypto2 + start_block: 12821148 + stop_block: 12831387 + expected_state: + protocol_components: + - id: "0xd51a44d3fae010294c616388b506acda1bfaae46" + tokens: + - "0xdac17f958d2ee523a2206206994597c13d831ec7" + - "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" + skip_simulation: true #TODO: investigate this failure + + - name: test_susd + start_block: 9906598 + stop_block: 9907338 + expected_state: + protocol_components: + - id: "0xa5407eae9ba41422680e2e00537571bcc53efbfd" + tokens: + - "0x6b175474e89094c44da98b954eedeac495271d0f" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + - "0xdac17f958d2ee523a2206206994597c13d831ec7" + - "0x57ab1ec28d129707052df4df418d58a2d46d5f51" + static_attributes: + creation_tx: "0x51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2" + skip_simulation: false + + - name: test_fraxusdc + start_block: 14939588 + stop_block: 14939712 + expected_state: + protocol_components: + - id: "0xdcef968d416a41cdac0ed8702fac8128a64241a2" + tokens: + - "0x853d955acef822db058eb8505911ed77f175b99e" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + static_attributes: + creation_tx: "0x1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775" + skip_simulation: false + - name: test_crypto_swap_ng_factory_plain_pool start_block: 18580701 stop_block: 18614742 @@ -106,7 +148,7 @@ tests: stop_block: 19163633 expected_state: protocol_components: - - id: "0x71db3764d6841d8b01dc27c0fd4a66a8a34b2be0" + - id: "0x71db3764d6841d8b01dc27c0fd4a66a8a34b2be0" #TODO: ADD TEST THAT USE WETH tokens: - "0x04c154b66cb340f3ae24111cc767e0184ed00cc6" - "0x4591dbff62656e7859afe5e45f6f47d3669fbb28" diff --git a/substreams/ethereum-curve/src/consts.rs b/substreams/ethereum-curve/src/consts.rs index 50181a8..7fc8ae8 100644 --- a/substreams/ethereum-curve/src/consts.rs +++ b/substreams/ethereum-curve/src/consts.rs @@ -15,3 +15,5 @@ pub const STABLESWAP_FACTORY: [u8; 20] = hex!("4F8846Ae9380B90d2E71D5e3D042dff3E // Important addresses pub const WETH_ADDRESS: [u8; 20] = hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); pub const ETH_ADDRESS: [u8; 20] = hex!("EeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"); +pub const OLD_SUSD: [u8; 20] = hex!("57Ab1E02fEE23774580C119740129eAC7081e9D3"); +pub const NEW_SUSD: [u8; 20] = hex!("57ab1ec28d129707052df4df418d58a2d46d5f51"); diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index 8c63055..b1d13e6 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -13,7 +13,7 @@ use substreams::{ use substreams_ethereum::pb::eth; use crate::{ - consts::{CRYPTO_SWAP_NG_FACTORY, TRICRYPTO_FACTORY}, + consts::{CRYPTO_SWAP_NG_FACTORY, NEW_SUSD, OLD_SUSD, TRICRYPTO_FACTORY}, pool_changes::emit_eth_deltas, pool_factories, pools::emit_specific_pools, @@ -157,15 +157,30 @@ pub fn map_relative_balances( .flat_map(|tx| { emit_eth_deltas(tx, &tokens_store) .into_iter() - .chain(extract_balance_deltas_from_tx(tx, |token, transactor| { - let pool_key = format!("pool:{}", hex::encode(transactor)); - if let Some(tokens) = tokens_store.get_last(pool_key) { - let token_id = hex::encode(token); - tokens.split(':').any(|t| t == token_id) - } else { - false - } - })) + .chain( + extract_balance_deltas_from_tx(tx, |token, transactor| { + let pool_key = format!("pool:{}", hex::encode(transactor)); + if let Some(tokens) = tokens_store.get_last(pool_key) { + let token_id; + if token == OLD_SUSD { + token_id = hex::encode(NEW_SUSD); + } else { + token_id = hex::encode(token); + } + tokens.split(':').any(|t| t == token_id) + } else { + false + } + }) + .into_iter() + .map(|mut balance| { + if balance.token == OLD_SUSD { + balance.token = NEW_SUSD.into(); + } + balance + }) + .collect::>(), + ) }) .collect(); From 65ac765284b0d249cab834545f84672fae521f34 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:13:08 +0200 Subject: [PATCH 04/13] refactor(curve): add utils functions on `ProtocolComponent` --- .../crates/tycho-substreams/src/models.rs | 82 +++++++++++++++++++ substreams/ethereum-curve/src/modules.rs | 30 ++----- 2 files changed, 90 insertions(+), 22 deletions(-) diff --git a/substreams/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs index 445baf5..333f172 100644 --- a/substreams/crates/tycho-substreams/src/models.rs +++ b/substreams/crates/tycho-substreams/src/models.rs @@ -300,6 +300,88 @@ impl ProtocolComponent { }); self } + + /// Checks if the instance contains all specified attributes. + /// + /// This function verifies whether the `ProtocolComponent` has all the given static attributes. + /// Each attribute is represented by a tuple containing a name and a value. The function + /// iterates over the provided attributes and checks if they exist in the instance's + /// `static_att`. + /// + /// # Arguments + /// + /// * `attributes` - A slice of tuples where each tuple consists of a `String` representing the + /// attribute name and a `Vec` representing the attribute value. + /// + /// # Returns + /// + /// A boolean indicating whether all specified attributes are present in the instance. + /// + /// # Example + /// + /// ``` + /// let attributes_to_check = vec![ + /// ("attribute1".to_string(), vec![1, 2, 3]), + /// ("attribute2".to_string(), vec![4, 5, 6]), + /// ]; + /// + /// let has_all_attributes = instance.has_attributes(&attributes_to_check); + /// assert!(has_all_attributes); + /// ``` + /// + /// # Notes + /// + /// - The function assumes that the `static_att` collection contains attributes with a + /// `ChangeType` of `Creation` when they are initially added. This is fine because + /// `static_att` can't be updated + pub fn has_attributes(&self, attributes: &[(&str, Vec)]) -> bool { + attributes.iter().all(|(name, value)| { + self.static_att.contains(&Attribute { + name: name.to_string(), + value: value.clone(), + change: ChangeType::Creation.into(), + }) + }) + } + + /// Retrieves the value of a specified attribute by name. + /// + /// This function searches the instance's `static_att` collection for an attribute with the + /// given name. If found, it returns a copy of the attribute's value. If the attribute is + /// not found, it returns `None`. + /// + /// # Arguments + /// + /// * `name` - A string slice that holds the name of the attribute to be searched. + /// + /// # Returns + /// + /// An `Option>` containing the attribute value if found, or `None` if the attribute + /// does not exist. + /// + /// # Example + /// + /// ``` + /// let attribute_name = "attribute1"; + /// if let Some(value) = instance.get_attribute_value(attribute_name) { + /// // Use the attribute value + /// println!("Attribute value: {:?}", value); + /// } else { + /// println!("Attribute not found"); + /// } + /// ``` + /// + /// # Notes + /// + /// - The function performs a search based on the attribute name and returns the first match + /// found. If there are multiple attributes with the same name, only the first one is + /// returned. + pub fn get_attribute_value(&self, name: &str) -> Option> { + self.static_att + .iter() + .find(|attr| attr.name == name) + .map(|attr| attr.value.clone()) + } } /// Same as `EntityChanges` but ensures attributes are unique by name. diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index b1d13e6..e2c1531 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -115,29 +115,15 @@ pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, sto .iter() .flat_map(|tx_components| &tx_components.components) .for_each(|component| { - // Crypto pool factory creates LP token separated from the pool, we need to index it so we add it to the store if the new protocol component comes from this factory - if component - .static_att - .contains(&Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }) && - component - .static_att - .contains(&Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }) - { + // Crypto pool factory creates LP token separated from the pool, we need to index it so + // we add it to the store if the new protocol component comes from this factory + if component.has_attributes(&[ + ("pool_type", "crypto_pool".into()), + ("factory_name", "crypto_pool_factory".into()), + ]) { let lp_token = component - .static_att - .iter() - .find(|attr| attr.name == "lp_token") - .unwrap() - .value - .clone(); + .get_attribute_value("lp_token") + .expect("didn't find lp_token attribute"); store.set(0, hex::encode(lp_token), &1); } }); From 9fa382ea6015ba67583c6d580ab2419d74bed1a3 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:13:44 +0200 Subject: [PATCH 05/13] refactor(curve): avoid RPC call when possible --- .../ethereum-curve/src/pool_factories.rs | 76 +++++++------------ 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index 4418022..dcaefe3 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -7,9 +7,8 @@ use substreams_ethereum::{ use crate::abi; use tycho_substreams::prelude::*; -use substreams::scalar::BigInt; - use crate::consts::*; +use substreams::scalar::BigInt; /// This trait defines some helpers for serializing and deserializing `Vec` which is needed /// to be able to encode some of the `Attribute`s. This should also be handled by any downstream @@ -85,11 +84,8 @@ pub fn address_map( let component_id = &call.return_data[12..]; - let pool_implementation = abi::crypto_pool_factory::functions::PoolImplementation {} - .call(CRYPTO_POOL_FACTORY.to_vec())?; - - let token_implementation = abi::crypto_pool_factory::functions::TokenImplementation {} - .call(CRYPTO_POOL_FACTORY.to_vec())?; + let token_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); + let pool_implementation = extract_proxy_impl(call, tx, 1).unwrap_or([1u8; 20]); Some(ProtocolComponent { id: hex::encode(component_id), @@ -192,12 +188,7 @@ pub fn address_map( .filter(|token| *token != [0; 20]) .collect(); - let pool_implementation = abi::meta_pool_factory::functions::PlainImplementations { - arg0: BigInt::from(tokens.len()), - arg1: add_pool.implementation_idx, - } - .call(META_POOL_FACTORY.to_vec())?; - + let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -274,13 +265,7 @@ pub fn address_map( abi::meta_registry::functions::GetLpToken1 { pool: add_pool.base_pool.clone() }; let lp_token = get_lp_token.call(META_REGISTRY.to_vec())?; - let pool_implementation = - abi::meta_pool_factory::functions::MetapoolImplementations { - base_pool: add_pool.base_pool.clone(), - } - .call(META_POOL_FACTORY.to_vec())? - [usize::try_from(add_pool.implementation_idx.to_u64()).unwrap()] - .clone(); + let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); Some(ProtocolComponent { id: hex::encode(component_id), @@ -360,20 +345,8 @@ pub fn address_map( call, ) })?; - let filtered: Vec<_> = tx - .calls - .iter() - .filter(|call| !call.account_creations.is_empty()) - .collect(); - let implementation = extract_eip1167_target_from_code( - filtered - .first()? - .code_changes - .first()? - .new_code - .clone(), - ); + let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); @@ -418,7 +391,9 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&implementation.try_into().unwrap()), + value: address_to_bytes_with_0x( + &pool_implementation.try_into().unwrap(), + ), change: ChangeType::Creation.into(), }, ], @@ -702,12 +677,7 @@ pub fn address_map( .filter(|token| *token != [0; 20]) .collect(); - let pool_implementation = - abi::stableswap_factory::functions::PlainImplementations { - arg0: BigInt::from(tokens.len()), - arg1: add_pool.implementation_idx, - } - .call(STABLESWAP_FACTORY.to_vec())?; + let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); Some(ProtocolComponent { id: hex::encode(component_id), @@ -944,19 +914,27 @@ fn get_token_from_pool(pool: &Vec) -> Vec { .unwrap() } -//TODO: We can most likely replace many RPC calls above using this function. -fn extract_eip1167_target_from_code(code: Vec) -> [u8; 20] { +fn extract_eip1167_target_from_code(code: &[u8]) -> [u8; 20] { let mut target = [0u8; 20]; - // Depending on the Vyper version, they use different implementation of EIP1167. + // Depending on the Vyper version, they use different implementations of EIP1167. // We use the first 10 bytes of the code to make a clear distinction. - match code[0..10] { - [54, 61, 61, 55, 61, 61, 61, 54, 61, 115] => target.copy_from_slice(&code[10..30]), - [54, 96, 0, 96, 0, 55, 97, 16, 0, 96] => target.copy_from_slice(&code[15..35]), - _ => { - panic!("unknown implementation") - } + match code.get(0..10) { + Some([54, 61, 61, 55, 61, 61, 61, 54, 61, 115]) => target.copy_from_slice(&code[10..30]), + Some([54, 96, 0, 96, 0, 55, 97, 16, 0, 96]) => target.copy_from_slice(&code[15..35]), + _ => target = [1u8; 20], // Placeholder for unexpected values } target } + +fn extract_proxy_impl(call: &Call, tx: &TransactionTrace, index: usize) -> Option<[u8; 20]> { + let code_change = tx + .calls + .iter() + .filter(|c| !c.code_changes.is_empty() && c.parent_index == call.index) + .nth(index)? + .code_changes + .first()?; + Some(extract_eip1167_target_from_code(&code_change.new_code)) +} From 388902b2ed2d612be203f659d0fd8f5ba0888030 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Mon, 5 Aug 2024 13:58:12 +0200 Subject: [PATCH 06/13] fix(curve): index tricrypto2 dependencies --- .../integration_test.tycho.yaml | 4 +- substreams/ethereum-curve/params.json | 103 ++++++++++-------- substreams/ethereum-curve/params.py | 5 +- substreams/ethereum-curve/src/consts.rs | 5 + substreams/ethereum-curve/src/modules.rs | 7 +- substreams/ethereum-curve/src/pools.rs | 17 ++- substreams/ethereum-curve/substreams.yaml | 2 +- 7 files changed, 86 insertions(+), 57 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index 8ff02ac..79e3ea1 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -34,7 +34,7 @@ tests: skip_simulation: false - name: test_tricrypto2 - start_block: 12821148 + start_block: 12821118 #This pool was created at 12821148, but it requires some contracts that were created shortly before. stop_block: 12831387 expected_state: protocol_components: @@ -45,7 +45,7 @@ tests: - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" static_attributes: creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" - skip_simulation: true #TODO: investigate this failure + skip_simulation: false - name: test_susd start_block: 9906598 diff --git a/substreams/ethereum-curve/params.json b/substreams/ethereum-curve/params.json index 23c01aa..f8f0db7 100644 --- a/substreams/ethereum-curve/params.json +++ b/substreams/ethereum-curve/params.json @@ -1,51 +1,58 @@ [ - { - "name": "3pool", - "address": "bebc44782c7db0a1a60cb6fe97d0b483032ff1c7", - "tx_hash": "20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6", - "tokens": [ - "6b175474e89094c44da98b954eedeac495271d0f", - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "dac17f958d2ee523a2206206994597c13d831ec7" - ] - }, - { - "name": "steth", - "address": "dc24316b9ae028f1497c275eb9192a3ea0f67022", - "tx_hash": "fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa", - "tokens": [ - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "ae7ab96520de3a18e5e111b5eaab095312d7fe84" - ] - }, - { - "name": "tricrypto2", - "address": "d51a44d3fae010294c616388b506acda1bfaae46", - "tx_hash": "dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138", - "tokens": [ - "dac17f958d2ee523a2206206994597c13d831ec7", - "2260fac5e5542a773aa44fbcfedf7c193bc2c599", - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - ] - }, - { - "name": "susd", - "address": "a5407eae9ba41422680e2e00537571bcc53efbfd", - "tx_hash": "51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2", - "tokens": [ - "6b175474e89094c44da98b954eedeac495271d0f", - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "dac17f958d2ee523a2206206994597c13d831ec7", - "57ab1ec28d129707052df4df418d58a2d46d5f51" - ] - }, - { - "name": "fraxusdc", - "address": "dcef968d416a41cdac0ed8702fac8128a64241a2", - "tx_hash": "1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775", - "tokens": [ - "853d955acef822db058eb8505911ed77f175b99e", - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - ] + { + "name": "3pool", + "address": "bebc44782c7db0a1a60cb6fe97d0b483032ff1c7", + "tx_hash": "20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6", + "tokens": [ + "6b175474e89094c44da98b954eedeac495271d0f", + "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "dac17f958d2ee523a2206206994597c13d831ec7" + ] + }, + { + "name": "steth", + "address": "dc24316b9ae028f1497c275eb9192a3ea0f67022", + "tx_hash": "fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa", + "tokens": [ + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "ae7ab96520de3a18e5e111b5eaab095312d7fe84" + ] + }, + { + "name": "tricrypto2", + "address": "d51a44d3fae010294c616388b506acda1bfaae46", + "contracts": [ + "c4ad29ba4b3c580e6d59105fff484999997675ff", + "40745803c2faa8e8402e2ae935933d07ca8f355c" + ], + "tx_hash": "dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138", + "tokens": [ + "dac17f958d2ee523a2206206994597c13d831ec7", + "2260fac5e5542a773aa44fbcfedf7c193bc2c599", + "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + ], + "attributes": { + "stateless_contract_addr_0": "0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5" } + }, + { + "name": "susd", + "address": "a5407eae9ba41422680e2e00537571bcc53efbfd", + "tx_hash": "51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2", + "tokens": [ + "6b175474e89094c44da98b954eedeac495271d0f", + "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "dac17f958d2ee523a2206206994597c13d831ec7", + "57ab1ec28d129707052df4df418d58a2d46d5f51" + ] + }, + { + "name": "fraxusdc", + "address": "dcef968d416a41cdac0ed8702fac8128a64241a2", + "tx_hash": "1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775", + "tokens": [ + "853d955acef822db058eb8505911ed77f175b99e", + "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + ] + } ] \ No newline at end of file diff --git a/substreams/ethereum-curve/params.py b/substreams/ethereum-curve/params.py index 8023c4c..de445d1 100644 --- a/substreams/ethereum-curve/params.py +++ b/substreams/ethereum-curve/params.py @@ -11,6 +11,7 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): try: for i, param in enumerate(params): address: str = param["address"] + contracts: str = param.get("contracts", []) tx_hash: str = param["tx_hash"] tokens: list[str] = param["tokens"] attributes: dict[str, str] = param.get("attributes", {}) @@ -19,6 +20,8 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): attributes["factory"] = EMPTY encoded_address = f"address={address}" + encoded_contracts = "&" + "&".join( + [f"contracts[]={contract}" for contract in contracts]) if contracts else '' encoded_tx_hash = f"tx_hash={tx_hash}" encoded_tokens = "&".join([f"tokens[]={token}" for token in tokens]) encoded_attributes = "&".join( @@ -28,7 +31,7 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): ] ) - encoded_param = f"{encoded_address}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}" + encoded_param = f"{encoded_address}{encoded_contracts}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}" encoded_param = encoded_param.rstrip("&") encoded_params.append(encoded_param) diff --git a/substreams/ethereum-curve/src/consts.rs b/substreams/ethereum-curve/src/consts.rs index 7fc8ae8..71f860b 100644 --- a/substreams/ethereum-curve/src/consts.rs +++ b/substreams/ethereum-curve/src/consts.rs @@ -17,3 +17,8 @@ pub const WETH_ADDRESS: [u8; 20] = hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc pub const ETH_ADDRESS: [u8; 20] = hex!("EeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"); pub const OLD_SUSD: [u8; 20] = hex!("57Ab1E02fEE23774580C119740129eAC7081e9D3"); pub const NEW_SUSD: [u8; 20] = hex!("57ab1ec28d129707052df4df418d58a2d46d5f51"); +pub const TRICRYPTO_2_LP: [u8; 20] = hex!("c4ad29ba4b3c580e6d59105fff484999997675ff"); +pub const TRICRYPTO_2_MATH_CONTRACT: [u8; 20] = hex!("40745803c2faa8e8402e2ae935933d07ca8f355c"); + +pub const CONTRACTS_TO_INDEX: [[u8; 20]; 4] = + [CRYPTO_SWAP_NG_FACTORY, TRICRYPTO_FACTORY, TRICRYPTO_2_LP, TRICRYPTO_2_MATH_CONTRACT]; diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index e2c1531..3baf032 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -13,7 +13,9 @@ use substreams::{ use substreams_ethereum::pb::eth; use crate::{ - consts::{CRYPTO_SWAP_NG_FACTORY, NEW_SUSD, OLD_SUSD, TRICRYPTO_FACTORY}, + consts::{ + CONTRACTS_TO_INDEX, NEW_SUSD, OLD_SUSD, + }, pool_changes::emit_eth_deltas, pool_factories, pools::emit_specific_pools, @@ -292,8 +294,7 @@ pub fn map_protocol_changes( non_component_accounts_store .get_last(hex::encode(addr)) .is_some() || - addr.eq(&CRYPTO_SWAP_NG_FACTORY) || - addr.eq(&TRICRYPTO_FACTORY) + CONTRACTS_TO_INDEX.contains(addr.try_into().expect("address should be 20 bytes long")) }, &mut transaction_changes, ); diff --git a/substreams/ethereum-curve/src/pools.rs b/substreams/ethereum-curve/src/pools.rs index 81d585a..5b7dced 100644 --- a/substreams/ethereum-curve/src/pools.rs +++ b/substreams/ethereum-curve/src/pools.rs @@ -9,6 +9,7 @@ const PARAMS_SEPERATOR: &str = ","; #[derive(Debug, Deserialize, PartialEq)] struct PoolQueryParams { address: String, + contracts: Option>, tx_hash: String, tokens: Vec, attribute_keys: Option>, @@ -72,8 +73,20 @@ fn create_component( change: ChangeType::Creation.into(), }) .collect::>(), - contracts: vec![hex::decode(pool.address.clone()) - .with_context(|| "Pool address was not formatted properly")?], + contracts: pool + .contracts + .clone() + .unwrap_or_default() + .into_iter() + .map(|contract| { + hex::decode(contract) + .with_context(|| "Pool contracts was not formatted properly") + }) + .chain(std::iter::once( + hex::decode(&pool.address) + .with_context(|| "Pool address was not formatted properly"), + )) + .collect::>>>()?, change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { name: "curve_pool".into(), diff --git a/substreams/ethereum-curve/substreams.yaml b/substreams/ethereum-curve/substreams.yaml index f46d6c6..b25e59e 100644 --- a/substreams/ethereum-curve/substreams.yaml +++ b/substreams/ethereum-curve/substreams.yaml @@ -75,4 +75,4 @@ modules: type: proto:tycho.evm.v1.BlockChanges params: - map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&attribute_keys[]=name&attribute_vals[]=3pool&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&attribute_keys[]=name&attribute_vals[]=steth&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=name&attribute_vals[]=tricrypto2&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&attribute_keys[]=name&attribute_vals[]=susd&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&attribute_keys[]=name&attribute_vals[]=fraxusdc&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000" + map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&attribute_keys[]=name&attribute_vals[]=3pool&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&attribute_keys[]=name&attribute_vals[]=steth&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&contracts[]=c4ad29ba4b3c580e6d59105fff484999997675ff&contracts[]=40745803c2faa8e8402e2ae935933d07ca8f355c&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=stateless_contract_addr_0&attribute_vals[]=0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5&attribute_keys[]=name&attribute_vals[]=tricrypto2&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&attribute_keys[]=name&attribute_vals[]=susd&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&attribute_keys[]=name&attribute_vals[]=fraxusdc&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000" From d8d7a6d9fdd711761341dcdccfa8f7e6240133f3 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 6 Aug 2024 10:28:44 +0200 Subject: [PATCH 07/13] fix(curve): add new missing initialized account and update Tycho binary --- substreams/ethereum-curve/integration_test.tycho.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index 79e3ea1..03800cf 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -81,6 +81,7 @@ tests: initialized_accounts: - "0x6a8cbed756804b16e05e741edabd5cb544ae21bf" - "0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963" # Needed by another component that is created within this block range + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range - "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" expected_state: protocol_components: @@ -113,6 +114,7 @@ tests: stop_block: 18029610 initialized_accounts: - "0xdcef968d416a41cdac0ed8702fac8128a64241a2" + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range expected_state: protocol_components: - id: "0x61fA2c947e523F9ABfb8d7e2903A5D5218C119a7" @@ -168,6 +170,7 @@ tests: stop_block: 17374457 initialized_accounts: - "0x0c0e5f2ff0ff18a3be9b835635039256dc4b4963" + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range expected_state: protocol_components: - id: "0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B" @@ -197,6 +200,8 @@ tests: - name: test_stableswap_factory_plain_pool start_block: 17258004 stop_block: 17260023 + initialized_accounts: + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range expected_state: protocol_components: - id: "0x390f3595bCa2Df7d23783dFd126427CCeb997BF4" From 6ac29335c744d8fef8c07ea75a92b830cb4bbdae Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:52:05 +0200 Subject: [PATCH 08/13] docs(curve-substreams): Add docs for each tests --- .../ethereum-curve/integration_test.tycho.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index 03800cf..b04a44c 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -6,6 +6,7 @@ skip_balance_check: true initialized_accounts: tests: + # Unique pool (no factory) 3pool - 0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7 - name: test_3pool start_block: 10809470 stop_block: 10810226 @@ -20,6 +21,7 @@ tests: creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6" skip_simulation: false + # Unique pool (no factory) steth - 0xdc24316b9ae028f1497c275eb9192a3ea0f67022 - name: test_steth start_block: 11592550 stop_block: 11595553 @@ -33,6 +35,7 @@ tests: creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" skip_simulation: false + # Unique pool (no factory) tricrypto2 - 0xd51a44d3fae010294c616388b506acda1bfaae46 - name: test_tricrypto2 start_block: 12821118 #This pool was created at 12821148, but it requires some contracts that were created shortly before. stop_block: 12831387 @@ -47,6 +50,7 @@ tests: creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" skip_simulation: false + # Unique pool (no factory) susd - 0xa5407eae9ba41422680e2e00537571bcc53efbfd - name: test_susd start_block: 9906598 stop_block: 9907338 @@ -62,6 +66,7 @@ tests: creation_tx: "0x51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2" skip_simulation: false + # Unique pool (no factory) fraxusdc - 0xdcef968d416a41cdac0ed8702fac8128a64241a2 - name: test_fraxusdc start_block: 14939588 stop_block: 14939712 @@ -75,6 +80,7 @@ tests: creation_tx: "0x1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775" skip_simulation: false + # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - PlainPool - name: test_crypto_swap_ng_factory_plain_pool start_block: 18580701 stop_block: 18614742 @@ -93,6 +99,7 @@ tests: creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" skip_simulation: false + # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - MetaPool - name: test_crypto_swap_ng_factory_meta_pool start_block: 19216042 stop_block: 19217045 @@ -109,6 +116,7 @@ tests: creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" skip_simulation: true # Reason: this pool use a base pool which is also one of its tokens, therefore our token override doesn't work here and it fails on transfers + # Metapool factory 0xB9fC157394Af804a3578134A6585C0dc9cc990d4 - MetaPool - name: test_metapool_factory_metapool start_block: 18028604 stop_block: 18029610 @@ -125,6 +133,7 @@ tests: creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply + # Metapool factory 0xB9fC157394Af804a3578134A6585C0dc9cc990d4 - PlainPool - name: test_metapool_factory_plainpool start_block: 18808555 stop_block: 18818577 @@ -145,6 +154,7 @@ tests: creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" skip_simulation: true # Reason: this pool has no liquidity at stop_block + # CryptoPool factory 0xF18056Bbd320E96A48e3Fbf8bC061322531aac99 - name: test_cryptopool_factory start_block: 19162590 stop_block: 19163633 @@ -165,6 +175,7 @@ tests: creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" skip_simulation: true # Reason: this pool has no liquidity at stop_block + # Tricrypto factory 0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963 - name: test_tricrypto_factory start_block: 17371455 stop_block: 17374457 @@ -182,6 +193,7 @@ tests: creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" skip_simulation: false + # Twocrypto factory 0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f - name: test_twocrypto_factory start_block: 19692166 stop_block: 19692232 @@ -197,6 +209,7 @@ tests: creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" skip_simulation: false + # StableSwap factory 0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d - PlainPool - name: test_stableswap_factory_plain_pool start_block: 17258004 stop_block: 17260023 @@ -212,6 +225,7 @@ tests: creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" skip_simulation: false + # StableSwap factory 0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d - Metapool # - name: test_stableswap_factory_meta_pool # There was no metapool created from this factory yet. # TODO: Double check https://etherscan.io/address/0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d#events search events with topic 0x01f31cd2abdeb4e5e10ba500f2db0f937d9e8c735ab04681925441b4ea37eda5. @@ -227,6 +241,7 @@ tests: # print(keccak(plain_pool_deployed)) # print(keccak(meta_pool_deployed)) + # Old MetaPool factory 0x0959158b6040D32d04c301A72CBFD6b39E21c9AE - name: test_metapool_factory_old start_block: 11968730 stop_block: 12028110 From 1f2316713f6b56c9cb01eb9c3d9eda32cea5da72 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:37:29 +0200 Subject: [PATCH 09/13] fix(curve): Update integration tests --- .../integration_test.tycho.yaml | 374 ++++++++++-------- testing/src/runner/models.py | 2 +- 2 files changed, 216 insertions(+), 160 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index b04a44c..f875e91 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -5,80 +5,90 @@ adapter_contract: "CurveAdapter" skip_balance_check: true initialized_accounts: tests: - # Unique pool (no factory) 3pool - 0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7 - name: test_3pool start_block: 10809470 stop_block: 10810226 - expected_state: - protocol_components: - - id: "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" - tokens: - - "0xdac17f958d2ee523a2206206994597c13d831ec7" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - - "0x6b175474e89094c44da98b954eedeac495271d0f" - static_attributes: - creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6" - skip_simulation: false + expected_components: + - id: "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" + tokens: + - "0xdac17f958d2ee523a2206206994597c13d831ec7" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + - "0x6b175474e89094c44da98b954eedeac495271d0f" + static_attributes: + factory_name: "0x6e61" # na + name: "0x33706f6f6c" # 3pool + factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 + creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6" + skip_simulation: false # Unique pool (no factory) steth - 0xdc24316b9ae028f1497c275eb9192a3ea0f67022 - name: test_steth start_block: 11592550 stop_block: 11595553 - expected_state: - protocol_components: - - id: "0xdc24316b9ae028f1497c275eb9192a3ea0f67022" - tokens: - - "0x0000000000000000000000000000000000000000" - - "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" - static_attributes: - creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" - skip_simulation: false + expected_components: + - id: "0xdc24316b9ae028f1497c275eb9192a3ea0f67022" + tokens: + - "0x0000000000000000000000000000000000000000" + - "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" + static_attributes: + factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 + name: "0x7374657468" # steth + factory_name: "0x6e61" # na + creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa" + skip_simulation: false # Unique pool (no factory) tricrypto2 - 0xd51a44d3fae010294c616388b506acda1bfaae46 - name: test_tricrypto2 start_block: 12821118 #This pool was created at 12821148, but it requires some contracts that were created shortly before. stop_block: 12831387 - expected_state: - protocol_components: - - id: "0xd51a44d3fae010294c616388b506acda1bfaae46" - tokens: - - "0xdac17f958d2ee523a2206206994597c13d831ec7" - - "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" - - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - static_attributes: - creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" - skip_simulation: false + expected_components: + - id: "0xd51a44d3fae010294c616388b506acda1bfaae46" + tokens: + - "0xdac17f958d2ee523a2206206994597c13d831ec7" + - "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 + stateless_contract_addr_0: "0x307838663638663438313063636533313934623663623666336435306661353863326339626464316435" # 0x8f68f4810cce3194b6cb6f3d50fa58c2c9bdd1d5 + factory_name: "0x6e61" # na + name: "0x74726963727970746f32" # tricrypto2 + creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" + skip_simulation: false # Unique pool (no factory) susd - 0xa5407eae9ba41422680e2e00537571bcc53efbfd - name: test_susd start_block: 9906598 stop_block: 9907338 - expected_state: - protocol_components: - - id: "0xa5407eae9ba41422680e2e00537571bcc53efbfd" - tokens: - - "0x6b175474e89094c44da98b954eedeac495271d0f" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - - "0xdac17f958d2ee523a2206206994597c13d831ec7" - - "0x57ab1ec28d129707052df4df418d58a2d46d5f51" - static_attributes: - creation_tx: "0x51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2" - skip_simulation: false + expected_components: + - id: "0xa5407eae9ba41422680e2e00537571bcc53efbfd" + tokens: + - "0x6b175474e89094c44da98b954eedeac495271d0f" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + - "0xdac17f958d2ee523a2206206994597c13d831ec7" + - "0x57ab1ec28d129707052df4df418d58a2d46d5f51" + static_attributes: + factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 + factory_name: "0x6e61" # na + name: "0x73757364" # susd + creation_tx: "0x51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2" + skip_simulation: false # Unique pool (no factory) fraxusdc - 0xdcef968d416a41cdac0ed8702fac8128a64241a2 - name: test_fraxusdc start_block: 14939588 stop_block: 14939712 - expected_state: - protocol_components: - - id: "0xdcef968d416a41cdac0ed8702fac8128a64241a2" - tokens: - - "0x853d955acef822db058eb8505911ed77f175b99e" - - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - static_attributes: - creation_tx: "0x1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775" - skip_simulation: false + expected_components: + - id: "0xdcef968d416a41cdac0ed8702fac8128a64241a2" + tokens: + - "0x853d955acef822db058eb8505911ed77f175b99e" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + static_attributes: + name: "0x6672617875736463" # fraxusdc + factory_name: "0x6e61" # na + factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 + creation_tx: "0x1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775" + skip_simulation: false # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - PlainPool - name: test_crypto_swap_ng_factory_plain_pool @@ -89,15 +99,19 @@ tests: - "0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963" # Needed by another component that is created within this block range - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range - "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" - expected_state: - protocol_components: - - id: "0x02950460E2b9529D0E00284A5fA2d7bDF3fA4d72" - tokens: - - "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" - - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - static_attributes: - creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" - skip_simulation: false + expected_components: + - id: "0x02950460E2b9529D0E00284A5fA2d7bDF3fA4d72" + tokens: + - "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" + - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + static_attributes: + factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf + factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory + name: "0x757364652d75736463" # usde-usdc + stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() + pool_type: "0x706c61696e5f706f6f6c" # plain_pool + creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" + skip_simulation: false # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - MetaPool - name: test_crypto_swap_ng_factory_meta_pool @@ -106,15 +120,21 @@ tests: initialized_accounts: - "0x6a8cbed756804b16e05e741edabd5cb544ae21bf" # Factory, needed for implementations contrats queries - "0xa5588f7cdf560811710a2d82d3c9c99769db1dcb" # Base pool of this meta pool - expected_state: - protocol_components: - - id: "0xef484de8C07B6e2d732A92B5F78e81B38f99f95E" - tokens: - - "0x865377367054516e17014CcdED1e7d814EDC9ce4" - - "0xa5588f7cdf560811710a2d82d3c9c99769db1dcb" - static_attributes: - creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" - skip_simulation: true # Reason: this pool use a base pool which is also one of its tokens, therefore our token override doesn't work here and it fails on transfers + expected_components: + - id: "0xef484de8C07B6e2d732A92B5F78e81B38f99f95E" + tokens: + - "0x865377367054516e17014CcdED1e7d814EDC9ce4" + - "0xa5588f7cdf560811710a2d82d3c9c99769db1dcb" + static_attributes: + factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory + name: "0x646f6c612f667261787079757364" # dola/fraxpyusd + pool_type: "0x6d657461706f6f6c" # metapool + stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() + stateless_contract_addr_1: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:math_implementation() + base_pool: "0x307861353538386637636466353630383131373130613264383264336339633939373639646231646362" # 0xa5588f7cdf560811710a2d82d3c9c99769db1dcb + factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf + creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" + skip_simulation: true # Reason: this pool use a base pool which is also one of its tokens, therefore our token override doesn't work here and it fails on transfers # Metapool factory 0xB9fC157394Af804a3578134A6585C0dc9cc990d4 - MetaPool - name: test_metapool_factory_metapool @@ -123,57 +143,84 @@ tests: initialized_accounts: - "0xdcef968d416a41cdac0ed8702fac8128a64241a2" - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range - expected_state: - protocol_components: - - id: "0x61fA2c947e523F9ABfb8d7e2903A5D5218C119a7" - tokens: - - "0x6c3ea9036406852006290770BEdFcAbA0e23A0e8" - - "0x3175Df0976dFA876431C2E9eE6Bc45b65d3473CC" - static_attributes: - creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" - skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply + expected_components: + - id: "0x61fA2c947e523F9ABfb8d7e2903A5D5218C119a7" + tokens: + - "0x6c3ea9036406852006290770BEdFcAbA0e23A0e8" + - "0x3175Df0976dFA876431C2E9eE6Bc45b65d3473CC" + static_attributes: + name: "0x70617970616c667261786270" # paypalfraxbp + factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory + base_pool: "0x307864636566393638643431366134316364616330656438373032666163383132386136343234316132" # 0xdcfe968d416ac0ed8702fac8128a64241a2 + factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d + pool_type: "0x6d657461706f6f6c" # metapool + stateless_contract_addr_0: "0x307833336262306536326435653863363838653634356464343664666234386364363133323530303637" # 0x33bb0e62d5e8c688e645dd46dfb48cd613250067 + creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" + skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply # Metapool factory 0xB9fC157394Af804a3578134A6585C0dc9cc990d4 - PlainPool - name: test_metapool_factory_plainpool start_block: 18808555 stop_block: 18818577 - expected_state: - protocol_components: - - id: "0xf2DCf6336D8250754B4527f57b275b19c8D5CF88" - tokens: - - "0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67" - - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" - static_attributes: - creation_tx: "0xeb34c90d352f18ffcfe78b7e393e155f0314acf06c54d1ac9996e4ee5a9b4742" - skip_simulation: false - - id: "0x3f67dc2AdBA4B1beB6A48c30AB3AFb1c1440d35B" - tokens: - - "0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67" - - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" - static_attributes: - creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" - skip_simulation: true # Reason: this pool has no liquidity at stop_block + expected_components: + - id: "0xf2DCf6336D8250754B4527f57b275b19c8D5CF88" + tokens: + - "0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67" + - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" + static_attributes: + name: "0x77737474616f2f7774616f" # wsttao/wtao + factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d + factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory + pool_type: "0x706c61696e5f706f6f6c" # plain_pool + stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 + creation_tx: "0xeb34c90d352f18ffcfe78b7e393e155f0314acf06c54d1ac9996e4ee5a9b4742" + skip_simulation: false + - id: "0x3f67dc2AdBA4B1beB6A48c30AB3AFb1c1440d35B" + tokens: + - "0xe9633C52f4c8B7BDeb08c4A7fE8a5c1B84AFCf67" + - "0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44" + static_attributes: + name: "0x77737474616f2f7774616f" # wsttao/wtao + factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d + factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory + pool_type: "0x706c61696e5f706f6f6c" # plain_pool + stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 + creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" + skip_simulation: true # Reason: this pool has no liquidity at stop_block # CryptoPool factory 0xF18056Bbd320E96A48e3Fbf8bC061322531aac99 - name: test_cryptopool_factory start_block: 19162590 stop_block: 19163633 - expected_state: - protocol_components: - - id: "0x71db3764d6841d8b01dc27c0fd4a66a8a34b2be0" #TODO: ADD TEST THAT USE WETH - tokens: - - "0x04c154b66cb340f3ae24111cc767e0184ed00cc6" - - "0x4591dbff62656e7859afe5e45f6f47d3669fbb28" - static_attributes: - creation_tx: "0xa89c09a7e0dfd84f3a294b8df4f33cc4a623e6d52deee357457afe2591ea596f" - skip_simulation: false - - id: "0x6c9Fe53cC13b125d6476E5Ce2b76983bd5b7A112" - tokens: - - "0x35fA164735182de50811E8e2E824cFb9B6118ac2" - - "0xf951E335afb289353dc249e82926178EaC7DEd78" - static_attributes: - creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" - skip_simulation: true # Reason: this pool has no liquidity at stop_block + expected_components: + - id: "0x71db3764d6841d8b01dc27c0fd4a66a8a34b2be0" #TODO: ADD TEST THAT USE WETH + tokens: + - "0x04c154b66cb340f3ae24111cc767e0184ed00cc6" + - "0x4591dbff62656e7859afe5e45f6f47d3669fbb28" + static_attributes: + name: "0x343030303030" # 400000 + pool_type: "0x63727970746f5f706f6f6c" # crypto_pool + factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 + factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory + lp_token: "0x6ade6971ca3d90990c30d39c78b0736c7166e07b" # 0x6ade6971ca3d90990c30d39c78b0736c7166e07b + stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 + stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 + creation_tx: "0xa89c09a7e0dfd84f3a294b8df4f33cc4a623e6d52deee357457afe2591ea596f" + skip_simulation: false + - id: "0x6c9Fe53cC13b125d6476E5Ce2b76983bd5b7A112" + tokens: + - "0x35fA164735182de50811E8e2E824cFb9B6118ac2" + - "0xf951E335afb289353dc249e82926178EaC7DEd78" + static_attributes: + name: "0x343030303030" # 400000 + pool_type: "0x63727970746f5f706f6f6c" # crypto_pool + factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 + factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory + lp_token: "0x94c4eba4f4b97be8d778f8c27027d676270e87a6" # 0x94c4eba4f4b97be8d778f8c27027d676270e87a6 + stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 + stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 + creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" + skip_simulation: true # Reason: this pool has no liquidity at stop_block # Tricrypto factory 0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963 - name: test_tricrypto_factory @@ -182,16 +229,22 @@ tests: initialized_accounts: - "0x0c0e5f2ff0ff18a3be9b835635039256dc4b4963" - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range - expected_state: - protocol_components: - - id: "0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B" - tokens: - - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - - "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" - - "0x0000000000000000000000000000000000000000" - static_attributes: - creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" - skip_simulation: false + expected_components: + - id: "0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B" + tokens: + - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + - "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" + - "0x0000000000000000000000000000000000000000" + static_attributes: + factory: "0x307830633065356632666630666631386133626539623833353633353033393235366463346234393633" # 0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963 + factory_name: "0x74726963727970746f5f666163746f7279" # tricrypto_factory + name: "0x74726963727970746f75736463" # tricrypto_usdc + stateless_contract_addr_0: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a76696577735f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:views_implementation() + stateless_contract_addr_1: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a6d6174685f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:math_implementation() + stateless_contract_addr_2: "0x307863303261616133396232323366653864306130653563346632376561643930383363373536636332" # 0xc02aaa39b223f8d0a0e5c4f27ead9083c756cc2 + pool_type: "0x74726963727970746f" # tricrypto + creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" + skip_simulation: false # Twocrypto factory 0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f - name: test_twocrypto_factory @@ -199,15 +252,20 @@ tests: stop_block: 19692232 initialized_accounts: - "0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f" # Factory, needed for implementations contracts queries - expected_state: - protocol_components: - - id: "0x77146B0a1d08B6844376dF6d9da99bA7F1b19e71" - tokens: - - "0x55C08ca52497e2f1534B59E2917BF524D4765257" - - "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - static_attributes: - creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" - skip_simulation: false + expected_components: + - id: "0x77146B0a1d08B6844376dF6d9da99bA7F1b19e71" + tokens: + - "0x55C08ca52497e2f1534B59E2917BF524D4765257" + - "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + static_attributes: + factory: "0x307839386565383531613030616265653064393564303863663463613262646365333261656161663766" # 0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f + pool_type: "0x74776f63727970746f" # twocrypto + factory_name: "0x74776f63727970746f5f666163746f7279" # twocrypto_factory + stateless_contract_addr_0: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a76696577735f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:views_implementation() + stateless_contract_addr_1: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:math_implementation() + name: "0x7577752f77657468" # uwu/weth + creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" + skip_simulation: false # StableSwap factory 0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d - PlainPool - name: test_stableswap_factory_plain_pool @@ -215,44 +273,42 @@ tests: stop_block: 17260023 initialized_accounts: - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range - expected_state: - protocol_components: - - id: "0x390f3595bCa2Df7d23783dFd126427CCeb997BF4" - tokens: - - "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E" - - "0xdAC17F958D2ee523a2206206994597C13D831ec7" - static_attributes: - creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" - skip_simulation: false + expected_components: + - id: "0x390f3595bCa2Df7d23783dFd126427CCeb997BF4" + tokens: + - "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E" + - "0xdAC17F958D2ee523a2206206994597C13D831ec7" + static_attributes: + name: "0x6372767573642f75736474" # crvusd/usdt + pool_type: "0x706c61696e5f706f6f6c" # plain_pool + factory: "0x307834663838343661653933383062393064326537316435653364303432646666336537656262343064" # 0x4f8846ae9380b90d2e71d5e3d042dff3e7ebb40d + factory_name: "0x737461626c655f737761705f666163746f7279" # stable_swap_factory + stateless_contract_addr_0: "0x307836376665343161393465373739636366613232636666303263633239353764633963306534323836" # 0x67fe41a94e779ccfa22cff02cc2957dc9c0e4286 + creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" + skip_simulation: false # StableSwap factory 0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d - Metapool # - name: test_stableswap_factory_meta_pool # There was no metapool created from this factory yet. - # TODO: Double check https://etherscan.io/address/0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d#events search events with topic 0x01f31cd2abdeb4e5e10ba500f2db0f937d9e8c735ab04681925441b4ea37eda5. - # Got the topic using: - # from web3 import Web3 - # - # def keccak(event): - # return Web3.keccak(text=event).hex() - # - # plain_pool_deployed = "PlainPoolDeployed(address[4],uint256,uint256,address,address)" - # meta_pool_deployed = "MetaPoolDeployed(address,address,uint256,uint256,address)" - # - # print(keccak(plain_pool_deployed)) - # print(keccak(meta_pool_deployed)) + # https://etherscan.io/address/0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d#events search events with topic 0x01f31cd2abdeb4e5e10ba500f2db0f937d9e8c735ab04681925441b4ea37eda5. + # related event is MetaPoolDeployed(address,address,uint256,uint256,address) - # Old MetaPool factory 0x0959158b6040D32d04c301A72CBFD6b39E21c9AE - name: test_metapool_factory_old start_block: 11968730 stop_block: 12028110 initialized_accounts: - "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7" # Linked pool of this metapool - expected_state: - protocol_components: - - id: "0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B" - tokens: - - "0x853d955aCEf822Db058eb8505911ED77F175b99e" - - "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490" - static_attributes: - creation_tx: "0x1f2a0d4e1c1eca594bd7f27f9952480ccda422c3453e0c5074a63aa46a2ed628" - skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply + expected_components: + - id: "0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B" + tokens: + - "0x853d955aCEf822Db058eb8505911ED77F175b99e" + - "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490" + static_attributes: + factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory + stateless_contract_addr_0: "0x307835663839303834316636353764393065303831626162646235333261303539393661663739666536" # 0x5f890841f657d90e081babdb532a05996af79fe6 + base_pool: "0x307862656263343437383263376462306131613630636236666539376430623438333033326666316337" # 0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7 + factory: "0x307830393539313538623630343064333264303463333031613732636266643662333965323163396165" # 0x0959158b6040d32d04c301a72cbfd6b39e21c9ae + pool_type: "0x6d657461706f6f6c" # metapool + name: "0x66726178" # frax + creation_tx: "0x1f2a0d4e1c1eca594bd7f27f9952480ccda422c3453e0c5074a63aa46a2ed628" + skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply diff --git a/testing/src/runner/models.py b/testing/src/runner/models.py index 6aeaae1..9c51260 100644 --- a/testing/src/runner/models.py +++ b/testing/src/runner/models.py @@ -66,7 +66,7 @@ class ProtocolComponentExpectation(BaseModel): colorize_diff(diff) if colorize_output else "\n".join(diff) ) differences.append( - f"Field '{field_name}' mismatch:\n{highlighted_diff}" + f"Field '{field_name}' mismatch for {self.id}:\n{highlighted_diff}" ) if not differences: return None From bd59af67edae5e9c183c37acf3b3d73d58a5f161 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:00:58 +0200 Subject: [PATCH 10/13] fix(curve): Add weth as stateless contract for CryptoPool with ETH --- .../integration_test.tycho.yaml | 21 +++++ .../ethereum-curve/src/pool_factories.rs | 90 +++++++++++-------- 2 files changed, 73 insertions(+), 38 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index f875e91..6c36efc 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -222,6 +222,27 @@ tests: creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" skip_simulation: true # Reason: this pool has no liquidity at stop_block + # CryptoPool factory 0xF18056Bbd320E96A48e3Fbf8bC061322531aac99 - with ETH + - name: test_cryptopool_factory + start_block: 19278886 + stop_block: 19278926 + expected_components: + - id: "0x99e09ee2d6Bb16c0F5ADDfEA649dbB2C1d524624" + tokens: + - "0x0000000000000000000000000000000000000000" + - "0x55296f69f40Ea6d20E478533C15A6B08B654E758" + static_attributes: + name: "0x343030303030" # 400000 + pool_type: "0x63727970746f5f706f6f6c" # crypto_pool + factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 + factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory + lp_token: "0x393dad6c76d962abba489a77dbf37ae948a4a6ee" # 0x393dad6c76d962abba489a77dbf37ae948a4a6ee + stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 + stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 + stateless_contract_addr_2: "0x307863303261616133396232323366653864306130653563346632376561643930383363373536636332" # 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 + creation_tx: "0x52f0f76d97e77579eebd32876de99f656930a99131dc4c4f1dec005786c8782b" + skip_simulation: false + # Tricrypto factory 0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963 - name: test_tricrypto_factory start_block: 17371455 diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index dcaefe3..2d5c6e1 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -87,6 +87,56 @@ pub fn address_map( let token_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); let pool_implementation = extract_proxy_impl(call, tx, 1).unwrap_or([1u8; 20]); + let mut static_attributes = vec![ + Attribute { + name: "pool_type".into(), + value: "crypto_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.a.to_string().into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "lp_token".into(), + value: pool_added.token.clone(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&pool_implementation.try_into().unwrap()), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(&token_implementation.try_into().unwrap()), + change: ChangeType::Creation.into(), + }, + ]; + + // This is relevant only if the contract has ETH + if tokens.contains(Ð_ADDRESS.into()) { + static_attributes.push(Attribute { + name: "stateless_contract_addr_2".into(), + // WETH + value: address_to_bytes_with_0x(&hex!( + "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + )), + change: ChangeType::Creation.into(), + }) + } + Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -96,44 +146,8 @@ pub fn address_map( index: tx.index.into(), }), tokens, - contracts: vec![component_id.into(), pool_added.token.clone()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.a.to_string().into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "lp_token".into(), - value: pool_added.token, - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&pool_implementation.try_into().unwrap()), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - value: address_to_bytes_with_0x(&token_implementation.try_into().unwrap()), - change: ChangeType::Creation.into(), - }, - ], + contracts: vec![component_id.into(), pool_added.token], + static_att: static_attributes, change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { name: "curve_pool".into(), From 5c25d2fac0811ccc45cb5909768a2e387f4ce60a Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:13:38 +0200 Subject: [PATCH 11/13] style(curve): Fix CI --- substreams/ethereum-curve/src/modules.rs | 18 +++---- .../ethereum-curve/src/pool_factories.rs | 48 ++++++++----------- substreams/ethereum-curve/src/pools.rs | 1 + 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index 3baf032..cf7eddb 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -13,9 +13,7 @@ use substreams::{ use substreams_ethereum::pb::eth; use crate::{ - consts::{ - CONTRACTS_TO_INDEX, NEW_SUSD, OLD_SUSD, - }, + consts::{CONTRACTS_TO_INDEX, NEW_SUSD, OLD_SUSD}, pool_changes::emit_eth_deltas, pool_factories, pools::emit_specific_pools, @@ -149,12 +147,11 @@ pub fn map_relative_balances( extract_balance_deltas_from_tx(tx, |token, transactor| { let pool_key = format!("pool:{}", hex::encode(transactor)); if let Some(tokens) = tokens_store.get_last(pool_key) { - let token_id; - if token == OLD_SUSD { - token_id = hex::encode(NEW_SUSD); + let token_id = if token == OLD_SUSD { + hex::encode(NEW_SUSD) } else { - token_id = hex::encode(token); - } + hex::encode(token) + }; tokens.split(':').any(|t| t == token_id) } else { false @@ -294,7 +291,10 @@ pub fn map_protocol_changes( non_component_accounts_store .get_last(hex::encode(addr)) .is_some() || - CONTRACTS_TO_INDEX.contains(addr.try_into().expect("address should be 20 bytes long")) + CONTRACTS_TO_INDEX.contains( + addr.try_into() + .expect("address should be 20 bytes long"), + ) }, &mut transaction_changes, ); diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index 2d5c6e1..babcea7 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -115,12 +115,12 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&pool_implementation.try_into().unwrap()), + value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), }, Attribute { name: "stateless_contract_addr_1".into(), - value: address_to_bytes_with_0x(&token_implementation.try_into().unwrap()), + value: address_to_bytes_with_0x(&token_implementation), change: ChangeType::Creation.into(), }, ]; @@ -236,9 +236,7 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x( - &pool_implementation.try_into().unwrap(), - ), + value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), }, ], @@ -321,9 +319,7 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x( - &pool_implementation.try_into().unwrap(), - ), + value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), }, ], @@ -405,9 +401,7 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x( - &pool_implementation.try_into().unwrap(), - ), + value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), }, ], @@ -467,8 +461,8 @@ pub fn address_map( name: "stateless_contract_addr_0".into(), // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY value: format!( - "call:{}:views_implementation()", - format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + "call:0x{}:views_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -536,8 +530,8 @@ pub fn address_map( name: "stateless_contract_addr_0".into(), // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY value: format!( - "call:{}:views_implementation()", - format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + "call:0x{}:views_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -546,8 +540,8 @@ pub fn address_map( name: "stateless_contract_addr_1".into(), // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY value: format!( - "call:{}:math_implementation()", - format!("0x{}", hex::encode(CRYPTO_SWAP_NG_FACTORY)) + "call:0x{}:math_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -595,8 +589,8 @@ pub fn address_map( name: "stateless_contract_addr_0".into(), // Call views_implementation() on TRICRYPTO_FACTORY value: format!( - "call:{}:views_implementation()", - format!("0x{}", hex::encode(TRICRYPTO_FACTORY)) + "call:0x{}:views_implementation()", + hex::encode(TRICRYPTO_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -605,8 +599,8 @@ pub fn address_map( name: "stateless_contract_addr_1".into(), // Call math_implementation() on TRICRYPTO_FACTORY value: format!( - "call:{}:math_implementation()", - format!("0x{}", hex::encode(TRICRYPTO_FACTORY)) + "call:0x{}:math_implementation()", + hex::encode(TRICRYPTO_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -726,9 +720,7 @@ pub fn address_map( }, Attribute { name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x( - &pool_implementation.try_into().unwrap(), - ), + value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), }, ], @@ -858,8 +850,8 @@ pub fn address_map( name: "stateless_contract_addr_0".into(), // Call views_implementation() on TWOCRYPTO_FACTORY value: format!( - "call:{}:views_implementation()", - format!("0x{}", hex::encode(TWOCRYPTO_FACTORY)) + "call:0x{}:views_implementation()", + hex::encode(TWOCRYPTO_FACTORY) ) .into(), change: ChangeType::Creation.into(), @@ -868,8 +860,8 @@ pub fn address_map( name: "stateless_contract_addr_1".into(), // Call math_implementation() on TWOCRYPTO_FACTORY value: format!( - "call:{}:math_implementation()", - format!("0x{}", hex::encode(TWOCRYPTO_FACTORY)) + "call:0x{}:math_implementation()", + hex::encode(TWOCRYPTO_FACTORY) ) .into(), change: ChangeType::Creation.into(), diff --git a/substreams/ethereum-curve/src/pools.rs b/substreams/ethereum-curve/src/pools.rs index 5b7dced..8aeef87 100644 --- a/substreams/ethereum-curve/src/pools.rs +++ b/substreams/ethereum-curve/src/pools.rs @@ -126,6 +126,7 @@ mod tests { "0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a".to_string(), PoolQueryParams { address: "0x5F890841f657d90E081bAbdB532A05996Af79Fe6".to_string(), + contracts: None, tx_hash: "0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a" .to_string(), tokens: vec![ From 420cf134660807c2332c088e8e5cb4c3a7e7e127 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:59:09 +0200 Subject: [PATCH 12/13] refactor(curve): Remove unnecessary WETH stateless contracts These contracts became unnecessary because we handle things differently on the Adapter side, we use native eth instead of WETH when possible. --- .../integration_test.tycho.yaml | 2 - .../ethereum-curve/src/pool_factories.rs | 188 ++++++++---------- 2 files changed, 80 insertions(+), 110 deletions(-) diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index 6c36efc..f0145d0 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -239,7 +239,6 @@ tests: lp_token: "0x393dad6c76d962abba489a77dbf37ae948a4a6ee" # 0x393dad6c76d962abba489a77dbf37ae948a4a6ee stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 - stateless_contract_addr_2: "0x307863303261616133396232323366653864306130653563346632376561643930383363373536636332" # 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 creation_tx: "0x52f0f76d97e77579eebd32876de99f656930a99131dc4c4f1dec005786c8782b" skip_simulation: false @@ -262,7 +261,6 @@ tests: name: "0x74726963727970746f75736463" # tricrypto_usdc stateless_contract_addr_0: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a76696577735f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:views_implementation() stateless_contract_addr_1: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a6d6174685f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:math_implementation() - stateless_contract_addr_2: "0x307863303261616133396232323366653864306130653563346632376561643930383363373536636332" # 0xc02aaa39b223f8d0a0e5c4f27ead9083c756cc2 pool_type: "0x74726963727970746f" # tricrypto creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" skip_simulation: false diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index babcea7..c116015 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -1,4 +1,3 @@ -use substreams::hex; use substreams_ethereum::{ pb::eth::v2::{Call, Log, TransactionTrace}, Event, Function, @@ -87,56 +86,6 @@ pub fn address_map( let token_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); let pool_implementation = extract_proxy_impl(call, tx, 1).unwrap_or([1u8; 20]); - let mut static_attributes = vec![ - Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.a.to_string().into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "lp_token".into(), - value: pool_added.token.clone(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&pool_implementation), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - value: address_to_bytes_with_0x(&token_implementation), - change: ChangeType::Creation.into(), - }, - ]; - - // This is relevant only if the contract has ETH - if tokens.contains(Ð_ADDRESS.into()) { - static_attributes.push(Attribute { - name: "stateless_contract_addr_2".into(), - // WETH - value: address_to_bytes_with_0x(&hex!( - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - )), - change: ChangeType::Creation.into(), - }) - } - Some(ProtocolComponent { id: hex::encode(component_id), tx: Some(Transaction { @@ -146,8 +95,44 @@ pub fn address_map( index: tx.index.into(), }), tokens, - contracts: vec![component_id.into(), pool_added.token], - static_att: static_attributes, + contracts: vec![component_id.into(), pool_added.token.clone()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "crypto_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.a.to_string().into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "lp_token".into(), + value: pool_added.token, + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&pool_implementation), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(&token_implementation), + change: ChangeType::Creation.into(), + }, + ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { name: "curve_pool".into(), @@ -564,60 +549,6 @@ pub fn address_map( abi::tricrypto_factory::events::TricryptoPoolDeployed::match_and_decode(log) { let tokens = swap_weth_for_eth(pool_added.coins.into()); - let mut static_attributes = vec![ - Attribute { - name: "pool_type".into(), - value: "tricrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "tricrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ]; - - // This is relevant only if the contract has ETH - if tokens.contains(Ð_ADDRESS.into()) { - static_attributes.push(Attribute { - name: "stateless_contract_addr_2".into(), - // WETH - value: address_to_bytes_with_0x(&hex!( - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - )), - change: ChangeType::Creation.into(), - }) - } Some(ProtocolComponent { id: hex::encode(&pool_added.pool), @@ -629,7 +560,48 @@ pub fn address_map( }), tokens, contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], - static_att: static_attributes, + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "tricrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "tricrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], change: ChangeType::Creation.into(), protocol_type: Some(ProtocolType { name: "curve_pool".into(), From c2182525480e2f6e199234ee83608bccfc092fde Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:42:06 +0200 Subject: [PATCH 13/13] refactor(curve): stateless contracts as state attribute instead of static. --- substreams/ethereum-curve/README.md | 13 +- .../integration_test.tycho.yaml | 23 +- substreams/ethereum-curve/params.py | 22 +- substreams/ethereum-curve/src/modules.rs | 151 +-- .../ethereum-curve/src/pool_factories.rs | 1109 +++++++++-------- substreams/ethereum-curve/src/pools.rs | 126 +- substreams/ethereum-curve/substreams.yaml | 10 +- 7 files changed, 775 insertions(+), 679 deletions(-) diff --git a/substreams/ethereum-curve/README.md b/substreams/ethereum-curve/README.md index fec075b..2bcc243 100644 --- a/substreams/ethereum-curve/README.md +++ b/substreams/ethereum-curve/README.md @@ -1,8 +1,11 @@ # Instructions -The run command for our substream is a little different here due to the inclusion of the dynamic parameters for manually admitted pools. +The run command for our substream is a little different here due to the inclusion of the dynamic parameters for manually +admitted pools. -This command will add extra parameters to the `map_components` module via the `python params.py` script. This embeds directly in the bash/zsh compatible command here. If `python` is not ideal, the script can be easily converted into `bash` but it would require the `jq` executable (I've used AI to convert it just fine in testing). +This command will add extra parameters to the `map_components` module via the `python params.py` script. This embeds +directly in the bash/zsh compatible command here. If `python` is not ideal, the script can be easily converted into +`bash` but it would require the `jq` executable (I've used AI to convert it just fine in testing). ```bash $ substreams run -e mainnet.eth.streamingfast.io:443 substreams.yaml map_protocol_changes --start-block 11507454 --stop-block +100 -p map_components=`python params.py` @@ -10,12 +13,14 @@ $ substreams run -e mainnet.eth.streamingfast.io:443 substreams.yaml map_protoco ## `params.json` -This json file is a top-level array containing objects that describe a specific `ProtocolComponent`. Each object contains the following fields: +This json file is a top-level array containing objects that describe a specific `ProtocolComponent`. Each object +contains the following fields: - `name`: Just for documentation purposes - `address`: The **lowercase** address of the component - `tx_hash`: The hash of the transaction where the component was emitted - `tokens`: A list of token addresses ordered in the exact same way as the Pool -- `attributes`: A nested object of key to value that represents the static attributes of the component. +- `static_attributes`: A nested object of key to value that represents the static attributes of the component. +- `attributes`: A nested object of key to value that represents attributes. Please see the included 3 examples for `3pool`, `steth`, and `tricrypto2`. diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index f0145d0..b579c9a 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -50,7 +50,6 @@ tests: - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" static_attributes: factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 - stateless_contract_addr_0: "0x307838663638663438313063636533313934623663623666336435306661353863326339626464316435" # 0x8f68f4810cce3194b6cb6f3d50fa58c2c9bdd1d5 factory_name: "0x6e61" # na name: "0x74726963727970746f32" # tricrypto2 creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" @@ -108,13 +107,12 @@ tests: factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory name: "0x757364652d75736463" # usde-usdc - stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() pool_type: "0x706c61696e5f706f6f6c" # plain_pool creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" skip_simulation: false # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - MetaPool - - name: test_crypto_swap_ng_factory_meta_pool + - name: test_crypto_swap_ng_factory_metapool start_block: 19216042 stop_block: 19217045 initialized_accounts: @@ -129,8 +127,6 @@ tests: factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory name: "0x646f6c612f667261787079757364" # dola/fraxpyusd pool_type: "0x6d657461706f6f6c" # metapool - stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:math_implementation() base_pool: "0x307861353538386637636466353630383131373130613264383264336339633939373639646231646362" # 0xa5588f7cdf560811710a2d82d3c9c99769db1dcb factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" @@ -154,7 +150,6 @@ tests: base_pool: "0x307864636566393638643431366134316364616330656438373032666163383132386136343234316132" # 0xdcfe968d416ac0ed8702fac8128a64241a2 factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d pool_type: "0x6d657461706f6f6c" # metapool - stateless_contract_addr_0: "0x307833336262306536326435653863363838653634356464343664666234386364363133323530303637" # 0x33bb0e62d5e8c688e645dd46dfb48cd613250067 creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply @@ -162,6 +157,8 @@ tests: - name: test_metapool_factory_plainpool start_block: 18808555 stop_block: 18818577 + initialized_accounts: + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range expected_components: - id: "0xf2DCf6336D8250754B4527f57b275b19c8D5CF88" tokens: @@ -172,7 +169,6 @@ tests: factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory pool_type: "0x706c61696e5f706f6f6c" # plain_pool - stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 creation_tx: "0xeb34c90d352f18ffcfe78b7e393e155f0314acf06c54d1ac9996e4ee5a9b4742" skip_simulation: false - id: "0x3f67dc2AdBA4B1beB6A48c30AB3AFb1c1440d35B" @@ -184,7 +180,6 @@ tests: factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory pool_type: "0x706c61696e5f706f6f6c" # plain_pool - stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" skip_simulation: true # Reason: this pool has no liquidity at stop_block @@ -203,8 +198,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x6ade6971ca3d90990c30d39c78b0736c7166e07b" # 0x6ade6971ca3d90990c30d39c78b0736c7166e07b - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 creation_tx: "0xa89c09a7e0dfd84f3a294b8df4f33cc4a623e6d52deee357457afe2591ea596f" skip_simulation: false - id: "0x6c9Fe53cC13b125d6476E5Ce2b76983bd5b7A112" @@ -217,8 +210,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x94c4eba4f4b97be8d778f8c27027d676270e87a6" # 0x94c4eba4f4b97be8d778f8c27027d676270e87a6 - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" skip_simulation: true # Reason: this pool has no liquidity at stop_block @@ -237,8 +228,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x393dad6c76d962abba489a77dbf37ae948a4a6ee" # 0x393dad6c76d962abba489a77dbf37ae948a4a6ee - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 creation_tx: "0x52f0f76d97e77579eebd32876de99f656930a99131dc4c4f1dec005786c8782b" skip_simulation: false @@ -259,8 +248,6 @@ tests: factory: "0x307830633065356632666630666631386133626539623833353633353033393235366463346234393633" # 0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963 factory_name: "0x74726963727970746f5f666163746f7279" # tricrypto_factory name: "0x74726963727970746f75736463" # tricrypto_usdc - stateless_contract_addr_0: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a76696577735f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a6d6174685f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:math_implementation() pool_type: "0x74726963727970746f" # tricrypto creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" skip_simulation: false @@ -280,8 +267,6 @@ tests: factory: "0x307839386565383531613030616265653064393564303863663463613262646365333261656161663766" # 0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f pool_type: "0x74776f63727970746f" # twocrypto factory_name: "0x74776f63727970746f5f666163746f7279" # twocrypto_factory - stateless_contract_addr_0: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a76696577735f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:math_implementation() name: "0x7577752f77657468" # uwu/weth creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" skip_simulation: false @@ -302,7 +287,6 @@ tests: pool_type: "0x706c61696e5f706f6f6c" # plain_pool factory: "0x307834663838343661653933383062393064326537316435653364303432646666336537656262343064" # 0x4f8846ae9380b90d2e71d5e3d042dff3e7ebb40d factory_name: "0x737461626c655f737761705f666163746f7279" # stable_swap_factory - stateless_contract_addr_0: "0x307836376665343161393465373739636366613232636666303263633239353764633963306534323836" # 0x67fe41a94e779ccfa22cff02cc2957dc9c0e4286 creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" skip_simulation: false @@ -324,7 +308,6 @@ tests: - "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490" static_attributes: factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory - stateless_contract_addr_0: "0x307835663839303834316636353764393065303831626162646235333261303539393661663739666536" # 0x5f890841f657d90e081babdb532a05996af79fe6 base_pool: "0x307862656263343437383263376462306131613630636236666539376430623438333033326666316337" # 0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7 factory: "0x307830393539313538623630343064333264303463333031613732636266643662333965323163396165" # 0x0959158b6040d32d04c301a72cbfd6b39e21c9ae pool_type: "0x6d657461706f6f6c" # metapool diff --git a/substreams/ethereum-curve/params.py b/substreams/ethereum-curve/params.py index de445d1..3085ce3 100644 --- a/substreams/ethereum-curve/params.py +++ b/substreams/ethereum-curve/params.py @@ -14,14 +14,18 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): contracts: str = param.get("contracts", []) tx_hash: str = param["tx_hash"] tokens: list[str] = param["tokens"] + static_attributes: dict[str, str] = param.get("static_attributes", {}) + static_attributes["name"] = param["name"] + static_attributes["factory_name"] = "NA" + static_attributes["factory"] = EMPTY attributes: dict[str, str] = param.get("attributes", {}) - attributes["name"] = param["name"] - attributes["factory_name"] = "NA" - attributes["factory"] = EMPTY encoded_address = f"address={address}" - encoded_contracts = "&" + "&".join( - [f"contracts[]={contract}" for contract in contracts]) if contracts else '' + encoded_contracts = ( + "&" + "&".join([f"contracts[]={contract}" for contract in contracts]) + if contracts + else "" + ) encoded_tx_hash = f"tx_hash={tx_hash}" encoded_tokens = "&".join([f"tokens[]={token}" for token in tokens]) encoded_attributes = "&".join( @@ -30,8 +34,14 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): for key, value in attributes.items() ] ) + encoded_static_attributes = "&".join( + [ + f"static_attribute_keys[]={key}&static_attribute_vals[]={value}" + for key, value in static_attributes.items() + ] + ) - encoded_param = f"{encoded_address}{encoded_contracts}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}" + encoded_param = f"{encoded_address}{encoded_contracts}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}&{encoded_static_attributes}" encoded_param = encoded_param.rstrip("&") encoded_params.append(encoded_param) diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index cf7eddb..3aa8551 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -36,63 +36,69 @@ impl PartialEq for TransactionWrapper { } #[substreams::handlers::map] -pub fn map_components( - params: String, - block: eth::v2::Block, -) -> Result { - // Gather contract changes by indexing `PoolCreated` events and analysing the `Create` call - // We store these as a hashmap by tx hash since we need to agg by tx hash later - Ok(BlockTransactionProtocolComponents { - tx_components: block - .transactions() - .filter_map(|tx| { - let mut components = tx - .logs_with_calls() - .filter(|(_, call)| !call.call.state_reverted) - .filter_map(|(log, call)| { - pool_factories::address_map( - call.call - .address - .as_slice() - .try_into() - .ok()?, // this shouldn't fail - log, - call.call, - tx, - ) - }) - .collect::>(); +// Map all created components and their related entity changes. +pub fn map_components(params: String, block: eth::v2::Block) -> Result { + let changes = block + .transactions() + .filter_map(|tx| { + let mut entity_changes = vec![]; + let mut components = vec![]; - if let Some(component) = emit_specific_pools(¶ms, tx).expect( - "An unexpected error occured when parsing params for emitting specific pools", + for (log, call) in tx + .logs_with_calls() + .filter(|(_, call)| !call.call.state_reverted) + { + if let Some((component, mut state)) = pool_factories::address_map( + call.call + .address + .as_slice() + .try_into() + .ok()?, // this shouldn't fail + log, + call.call, + tx, ) { - components.push(component) + entity_changes.append(&mut state); + components.push(component); } + } - if !components.is_empty() { - Some(TransactionProtocolComponents { - tx: Some(Transaction { - hash: tx.hash.clone(), - from: tx.from.clone(), - to: tx.to.clone(), - index: Into::::into(tx.index), - }), - components, - }) - } else { - None - } - }) - .collect::>(), - }) + if let Some((component, mut state)) = emit_specific_pools(¶ms, tx).expect( + "An unexpected error occured when parsing params for emitting specific pools", + ) { + entity_changes.append(&mut state); + components.push(component); + } + + if components.is_empty() { + None + } else { + Some(TransactionChanges { + tx: Some(Transaction { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + }), + contract_changes: vec![], + entity_changes, + component_changes: components, + balance_changes: vec![], + }) + } + }) + .collect::>(); + + Ok(BlockChanges { block: None, changes }) } -/// Simply stores the `ProtocolComponent`s with the pool id as the key and tokens as the value +/// Get result `map_components` and stores the created `ProtocolComponent`s with the pool id as the +/// key and tokens as the value #[substreams::handlers::store] -pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: StoreSetString) { - map.tx_components +pub fn store_component_tokens(map: BlockChanges, store: StoreSetString) { + map.changes .iter() - .flat_map(|tx_components| &tx_components.components) + .flat_map(|tx_changes| &tx_changes.component_changes) .for_each(|component| { store.set( 0, @@ -110,10 +116,10 @@ pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: St /// pool. /// This is later used to index them with `extract_contract_changes` #[substreams::handlers::store] -pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, store: StoreSetInt64) { - map.tx_components +pub fn store_non_component_accounts(map: BlockChanges, store: StoreSetInt64) { + map.changes .iter() - .flat_map(|tx_components| &tx_components.components) + .flat_map(|tx_changes| &tx_changes.component_changes) .for_each(|component| { // Crypto pool factory creates LP token separated from the pool, we need to index it so // we add it to the store if the new protocol component comes from this factory @@ -194,7 +200,7 @@ pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { #[substreams::handlers::map] pub fn map_protocol_changes( block: eth::v2::Block, - grouped_components: BlockTransactionProtocolComponents, + grouped_components: BlockChanges, deltas: BlockBalanceDeltas, components_store: StoreGetString, non_component_accounts_store: StoreGetInt64, @@ -204,14 +210,14 @@ pub fn map_protocol_changes( // sort them at the very end. let mut transaction_changes: HashMap<_, TransactionChanges> = HashMap::new(); - // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to - // convert into `TransactionChanges` + // `ProtocolComponents` are gathered with some entity changes from `map_pools_created` which + // just need a bit of work to convert into `TransactionChanges` grouped_components - .tx_components + .changes .into_iter() - .for_each(|tx_component| { - let tx = tx_component.tx.as_ref().unwrap(); - transaction_changes + .for_each(|tx_changes| { + let tx = tx_changes.tx.as_ref().unwrap(); + let transaction_entry = transaction_changes .entry(tx.index) .or_insert_with(|| TransactionChanges { tx: Some(tx.clone()), @@ -219,18 +225,23 @@ pub fn map_protocol_changes( component_changes: vec![], balance_changes: vec![], entity_changes: vec![], - }) + }); + + let formated_components: Vec<_> = tx_changes //TODO: format directly at creation .component_changes - .extend_from_slice( - &(tx_component - .components - .into_iter() - .map(|mut component| { - component.id = format!("0x{}", component.id); - component - }) - .collect::>()), - ); + .into_iter() + .map(|mut component| { + component.id = format!("0x{}", component.id); + component + }) + .collect(); + + transaction_entry + .component_changes + .extend(formated_components); + transaction_entry + .entity_changes + .extend(tx_changes.entity_changes); }); // Balance changes are gathered by the `StoreDelta` based on `TokenExchange`, etc. creating diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index c116015..a52e249 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -32,9 +32,14 @@ impl SerializableVecBigInt for Vec { } } -/// Converts address bytes into a string containing a leading `0x`. +/// Converts address bytes into a Vec containing a leading `0x`. fn address_to_bytes_with_0x(address: &[u8; 20]) -> Vec { - format!("0x{}", hex::encode(address)).into_bytes() + address_to_string_with_0x(address).into_bytes() +} + +/// Converts address bytes into a string containing a leading `0x`. +fn address_to_string_with_0x(address: &[u8]) -> String { + format!("0x{}", hex::encode(address)) } /// Function that swaps `WETH` addresses for `ETH` address for specific factory types that decide @@ -52,9 +57,9 @@ fn swap_weth_for_eth(tokens: Vec>) -> Vec> { } /// This massive function matches factory address to specific logic to construct -/// `ProtocolComponent`s. While, most of the logic is readily replicable, several factories differ -/// in information density resulting in needing other information sources such as decoding calls -/// or even making RPC calls to provide extra details. +/// `ProtocolComponent`s and their related `EntityChanges` at creation. While, most of the logic is +/// readily replicable, several factories differ in information density resulting in needing other +/// information sources such as decoding calls or even making RPC calls to provide extra details. /// /// Each `ProtocolComponent` contains the following static attributes: /// - `pool_type`: The type of pool, such as `crypto_pool`, `plain_pool`, `metapool`, etc. @@ -73,7 +78,7 @@ pub fn address_map( log: &Log, call: &Call, tx: &TransactionTrace, -) -> Option { +) -> Option<(ProtocolComponent, Vec)> { match *call_address { CRYPTO_POOL_FACTORY => { let pool_added = @@ -86,61 +91,68 @@ pub fn address_map( let token_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); let pool_implementation = extract_proxy_impl(call, tx, 1).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into(), pool_added.token.clone()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.a.to_string().into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "lp_token".into(), - value: pool_added.token, - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&pool_implementation), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - value: address_to_bytes_with_0x(&token_implementation), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into(), pool_added.token.clone()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "crypto_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.a.to_string().into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "lp_token".into(), + value: pool_added.token, + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&pool_implementation), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(&token_implementation), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } META_POOL_FACTORY => { if let Some(pool_added) = @@ -188,51 +200,56 @@ pub fn address_map( .collect(); let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::meta_pool_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -264,58 +281,63 @@ pub fn address_map( let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into(), add_pool.base_pool.clone()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &add_pool.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into(), add_pool.base_pool.clone()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &add_pool.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else { None } @@ -346,58 +368,63 @@ pub fn address_map( let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY_OLD), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &add_pool.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY_OLD), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &add_pool.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else { None } @@ -411,38 +438,50 @@ pub fn address_map( call, )?; let component_id = &call.return_data[12..]; - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool_added.coins, - contracts: vec![component_id.into(), CRYPTO_SWAP_NG_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_swap_ng_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool_added.coins, + contracts: vec![component_id.into(), CRYPTO_SWAP_NG_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_swap_ng_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY value: format!( @@ -451,16 +490,9 @@ pub fn address_map( ) .into(), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::crypto_swap_ng_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -469,77 +501,84 @@ pub fn address_map( let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![ - component_id.into(), - CRYPTO_SWAP_NG_FACTORY.into(), - pool_added.base_pool.clone(), - ], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_swap_ng_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &pool_added.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(CRYPTO_SWAP_NG_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(CRYPTO_SWAP_NG_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![ + component_id.into(), + CRYPTO_SWAP_NG_FACTORY.into(), + pool_added.base_pool.clone(), + ], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_swap_ng_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &pool_added.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } @@ -549,67 +588,75 @@ pub fn address_map( abi::tricrypto_factory::events::TricryptoPoolDeployed::match_and_decode(log) { let tokens = swap_weth_for_eth(pool_added.coins.into()); + let id = hex::encode(&pool_added.pool); - Some(ProtocolComponent { - id: hex::encode(&pool_added.pool), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "tricrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "tricrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: id.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "tricrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "tricrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } @@ -659,51 +706,56 @@ pub fn address_map( let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "stable_swap_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "stable_swap_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::stableswap_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -732,53 +784,56 @@ pub fn address_map( abi::meta_registry::functions::GetLpToken1 { pool: add_pool.base_pool.clone() }; let lp_token = get_lp_token.call(META_REGISTRY.to_vec())?; - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "stable_swap_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &pool_added.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "stable_swap_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &pool_added.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![], + )) } else { None } @@ -787,66 +842,74 @@ pub fn address_map( if let Some(pool_added) = abi::twocrypto_factory::events::TwocryptoPoolDeployed::match_and_decode(log) { - Some(ProtocolComponent { - id: hex::encode(&pool_added.pool), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool_added.coins.into(), - contracts: vec![pool_added.pool, TWOCRYPTO_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "twocrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "twocrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on TWOCRYPTO_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(TWOCRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on TWOCRYPTO_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(TWOCRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + let id = hex::encode(&pool_added.pool); + Some(( + ProtocolComponent { + id: id.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool_added.coins.into(), + contracts: vec![pool_added.pool, TWOCRYPTO_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "twocrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "twocrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(TWOCRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(TWOCRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } diff --git a/substreams/ethereum-curve/src/pools.rs b/substreams/ethereum-curve/src/pools.rs index 8aeef87..a8ca576 100644 --- a/substreams/ethereum-curve/src/pools.rs +++ b/substreams/ethereum-curve/src/pools.rs @@ -12,6 +12,8 @@ struct PoolQueryParams { contracts: Option>, tx_hash: String, tokens: Vec, + static_attribute_keys: Option>, + static_attribute_vals: Option>, attribute_keys: Option>, attribute_vals: Option>, } @@ -32,7 +34,7 @@ struct PoolQueryParams { pub fn emit_specific_pools( params: &str, tx: &TransactionTrace, -) -> Result> { +) -> Result)>> { let pools = parse_params(params)?; create_component(tx, pools) } @@ -40,61 +42,81 @@ pub fn emit_specific_pools( fn create_component( tx: &TransactionTrace, pools: HashMap, -) -> Result> { +) -> Result)>> { let encoded_hash = hex::encode(tx.hash.clone()); if let Some(pool) = pools.get(&encoded_hash) { - Ok(Some(ProtocolComponent { - id: pool.address.clone(), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool - .tokens - .clone() - .into_iter() - .map(|token| Result::Ok(hex::decode(token)?)) - .collect::>>() - .with_context(|| "Token addresses were not formatted properly")?, - static_att: zip( - pool.attribute_keys + Ok(Some(( + ProtocolComponent { + id: pool.address.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool + .tokens .clone() - .unwrap_or(vec![]), - pool.attribute_vals - .clone() - .unwrap_or(vec![]), - ) - .clone() - .map(|(key, value)| Attribute { - name: key, - value: value.into(), - change: ChangeType::Creation.into(), - }) - .collect::>(), - contracts: pool - .contracts + .into_iter() + .map(|token| Result::Ok(hex::decode(token)?)) + .collect::>>() + .with_context(|| "Token addresses were not formatted properly")?, + static_att: zip( + pool.static_attribute_keys + .clone() + .unwrap_or(vec![]), + pool.static_attribute_vals + .clone() + .unwrap_or(vec![]), + ) .clone() - .unwrap_or_default() - .into_iter() - .map(|contract| { - hex::decode(contract) - .with_context(|| "Pool contracts was not formatted properly") + .map(|(key, value)| Attribute { + name: key, + value: value.into(), + change: ChangeType::Creation.into(), }) - .chain(std::iter::once( - hex::decode(&pool.address) - .with_context(|| "Pool address was not formatted properly"), - )) - .collect::>>>()?, - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - })) + .collect::>(), + contracts: pool + .contracts + .clone() + .unwrap_or_default() + .into_iter() + .map(|contract| { + hex::decode(contract) + .with_context(|| "Pool contracts was not formatted properly") + }) + .chain(std::iter::once( + hex::decode(&pool.address) + .with_context(|| "Pool address was not formatted properly"), + )) + .collect::>>>()?, + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", pool.address.clone()), + attributes: zip( + pool.attribute_keys + .clone() + .unwrap_or(vec![]), + pool.attribute_vals + .clone() + .unwrap_or(vec![]), + ) + .clone() + .map(|(key, value)| Attribute { + name: key, + value: value.into(), + change: ChangeType::Creation.into(), + }) + .collect::>(), + }], + ))) } else { Ok(None) } @@ -134,6 +156,8 @@ mod tests { "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string(), "0xdac17f958d2ee523a2206206994597c13d831ec7".to_string(), ], + static_attribute_keys: None, + static_attribute_vals: None, attribute_keys: Some(vec!["key1".to_string()]), attribute_vals: Some(vec!["val1".to_string()]), }, diff --git a/substreams/ethereum-curve/substreams.yaml b/substreams/ethereum-curve/substreams.yaml index b25e59e..34ff1b8 100644 --- a/substreams/ethereum-curve/substreams.yaml +++ b/substreams/ethereum-curve/substreams.yaml @@ -20,12 +20,12 @@ binaries: modules: - name: map_components kind: map - initialBlock: 9906598 + initialBlock: 9906598 # Creation of first Curve pool 0xa5407eae9ba41422680e2e00537571bcc53efbfd inputs: - params: string - source: sf.ethereum.type.v2.Block output: - type: proto:tycho.evm.v1.BlockTransactionProtocolComponents + type: proto:tycho.evm.v1.BlockChanges - name: store_component_tokens kind: store @@ -37,7 +37,7 @@ modules: - name: store_non_component_accounts kind: store - initialBlock: 11968730 + initialBlock: 9906598 updatePolicy: set valueType: int64 inputs: @@ -45,7 +45,7 @@ modules: - name: map_relative_balances kind: map - initialBlock: 9906598 # An arbitrary block that should change based on your requirements + initialBlock: 9906598 inputs: - source: sf.ethereum.type.v2.Block - store: store_component_tokens @@ -75,4 +75,4 @@ modules: type: proto:tycho.evm.v1.BlockChanges params: - map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&attribute_keys[]=name&attribute_vals[]=3pool&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&attribute_keys[]=name&attribute_vals[]=steth&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&contracts[]=c4ad29ba4b3c580e6d59105fff484999997675ff&contracts[]=40745803c2faa8e8402e2ae935933d07ca8f355c&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=stateless_contract_addr_0&attribute_vals[]=0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5&attribute_keys[]=name&attribute_vals[]=tricrypto2&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&attribute_keys[]=name&attribute_vals[]=susd&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&attribute_keys[]=name&attribute_vals[]=fraxusdc&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000" + map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&&static_attribute_keys[]=name&static_attribute_vals[]=3pool&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&&static_attribute_keys[]=name&static_attribute_vals[]=steth&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&contracts[]=c4ad29ba4b3c580e6d59105fff484999997675ff&contracts[]=40745803c2faa8e8402e2ae935933d07ca8f355c&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=stateless_contract_addr_0&attribute_vals[]=0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5&static_attribute_keys[]=name&static_attribute_vals[]=tricrypto2&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&&static_attribute_keys[]=name&static_attribute_vals[]=susd&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&&static_attribute_keys[]=name&static_attribute_vals[]=fraxusdc&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000"