From b3909a414040a102a8307bc25f977c3086c91e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alan=20H=C3=B6ng?= Date: Thu, 7 Mar 2024 10:08:36 +0000 Subject: [PATCH 01/37] GITBOOK-7: Specify byte encoding rules --- docs/indexing/substreams-integration.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/indexing/substreams-integration.md b/docs/indexing/substreams-integration.md index 0bbb12e..5572939 100644 --- a/docs/indexing/substreams-integration.md +++ b/docs/indexing/substreams-integration.md @@ -42,6 +42,18 @@ The models below are very similar to the vm integration models but have a few mo Once again changes must be aggregated on a transaction level, emitting these models with duplicated transaction as the final output would be considered an error. +#### Integer Byte encoding + +Many of the types above are variable length bytes. This allows for flexibility across blockchains but require agreeing on an informal interface, so later applications know how to interpret these bytes. + +**Integers:** especially integers used to communicate balances, should always be encoded as unsigned big-endian integer. This is simply because balances serve multiple purposes within the system and need to be decoded in multiple location of the messages journey. + +**Strings**: If you need to store strings, please use utf-8 encoding to store them as bytes. + +**Attributes:** the value encoding for attributes in the native implementation messages is variable. It depends on the use case. Since the attributes are highly dynamic they are only used by the corresponding logic components, so the encoding can be tailored to the logic implementation: E.g. since Rust uses little endian one may choose to use little endian encoding for integers if the native logic module is written in Rust. + + + ### Changes of interest PropellerHeads integration should at least communicate the following changes: From b8d7f6686c7e63d85378bbdec3abdde53f39311d Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:39:07 +0100 Subject: [PATCH 02/37] Fix balancer substream naming --- substreams/Readme.md | 2 +- substreams/ethereum-balancer/Cargo.toml | 4 ++-- substreams/ethereum-balancer/substreams.yaml | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/substreams/Readme.md b/substreams/Readme.md index f4f9aa3..530d858 100644 --- a/substreams/Readme.md +++ b/substreams/Readme.md @@ -47,7 +47,7 @@ The example from the official docs will serve us just well: ```toml [package] -name = "substreams_[CHAIN]_[PROTOCOL_SYSTEM]" +name = "substreams-[CHAIN]-[PROTOCOL_SYSTEM]" version = "0.1.0" edition = "2021" diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml index 795c565..ace53d3 100644 --- a/substreams/ethereum-balancer/Cargo.toml +++ b/substreams/ethereum-balancer/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "substreams-balancer" +name = "substreams-ethereum-balancer" version = "0.1.0" edition = "2021" [lib] -name = "substreams_balancer" +name = "substreams_ethereum_balancer" crate-type = ["cdylib"] [dependencies] diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 6324d2b..f1bc3af 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -1,6 +1,6 @@ specVersion: v0.1.0 package: - name: "substreams_balancer" + name: "substreams_ethereum_balancer" version: v0.1.0 protobuf: @@ -14,7 +14,7 @@ protobuf: binaries: default: type: wasm/rust-v1 - file: target/wasm32-unknown-unknown/release/substreams_balancer.wasm + file: target/wasm32-unknown-unknown/release/substreams_ethereum_balancer.wasm modules: - name: map_pools_created @@ -35,7 +35,7 @@ modules: - name: map_balance_deltas kind: map - initialBlock: 12369300 # An arbitrary block that should change based on your requirements + initialBlock: 12369300 # An arbitrary block that should change based on your requirements inputs: - source: sf.ethereum.type.v2.Block - store: store_pools_created @@ -59,6 +59,6 @@ modules: - map: map_balance_deltas - store: store_pools_created - store: store_balance_changes - mode: deltas # This is the key property that simplifies `BalanceChange` handling + mode: deltas # This is the key property that simplifies `BalanceChange` handling output: type: proto:tycho.evm.v1.BlockContractChanges From 66a048fbe2333c3cdcf17ae4c07914bc565fa07b Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:45:58 +0100 Subject: [PATCH 03/37] refactor: update protobuf messages --- proto/tycho/evm/v1/balancer.proto | 32 ++++ proto/tycho/evm/v1/common.proto | 27 ++- substreams/ethereum-balancer/Cargo.lock | 36 ++-- .../ethereum-balancer/proto/factory.proto | 19 --- substreams/ethereum-balancer/proto/pool.proto | 15 -- .../proto/tycho/evm/v1/common.proto | 113 ------------- .../proto/tycho/evm/v1/entity.proto | 32 ---- .../proto/tycho/evm/v1/vm.proto | 50 ------ substreams/ethereum-balancer/src/modules.rs | 11 +- .../src/pb/eth.balancer.v1.rs | 28 ---- .../src/pb/eth.factory.v1.rs | 28 ---- .../ethereum-balancer/src/pb/eth.pool.v1.rs | 22 --- .../ethereum-balancer/src/pb/tycho.evm.v1.rs | 158 +++++++++++++----- .../ethereum-balancer/src/pool_factories.rs | 66 +++++++- substreams/ethereum-balancer/substreams.yaml | 4 +- 15 files changed, 261 insertions(+), 380 deletions(-) create mode 100644 proto/tycho/evm/v1/balancer.proto delete mode 100644 substreams/ethereum-balancer/proto/factory.proto delete mode 100644 substreams/ethereum-balancer/proto/pool.proto delete mode 100644 substreams/ethereum-balancer/proto/tycho/evm/v1/common.proto delete mode 100644 substreams/ethereum-balancer/proto/tycho/evm/v1/entity.proto delete mode 100644 substreams/ethereum-balancer/proto/tycho/evm/v1/vm.proto delete mode 100644 substreams/ethereum-balancer/src/pb/eth.balancer.v1.rs delete mode 100644 substreams/ethereum-balancer/src/pb/eth.factory.v1.rs delete mode 100644 substreams/ethereum-balancer/src/pb/eth.pool.v1.rs diff --git a/proto/tycho/evm/v1/balancer.proto b/proto/tycho/evm/v1/balancer.proto new file mode 100644 index 0000000..f5a4c63 --- /dev/null +++ b/proto/tycho/evm/v1/balancer.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package tycho.evm.v1; + +import "tycho/evm/v1/common.proto"; + +// A struct for following the changes of Total Value Locked (TVL). +message BalanceDelta { + uint64 ord = 1; + // The tx hash of the transaction that caused the balance change. + Transaction tx = 2; + // The address of the ERC20 token whose balance changed. + bytes token = 3; + // The delta balance of the token. + bytes delta = 4; + // The id of the component whose TVL is tracked. + // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + bytes component_id = 5; +} + +message BalanceDeltas { + repeated BalanceDelta balance_deltas = 1; +} + +message TransactionProtocolComponents { + Transaction tx = 1; + repeated ProtocolComponent components = 2; +} + +message GroupedTransactionProtocolComponents { + repeated TransactionProtocolComponents tx_components = 1; +} \ No newline at end of file diff --git a/proto/tycho/evm/v1/common.proto b/proto/tycho/evm/v1/common.proto index d52dbed..545cad0 100644 --- a/proto/tycho/evm/v1/common.proto +++ b/proto/tycho/evm/v1/common.proto @@ -25,6 +25,7 @@ message Transaction { // The receiver of the transaction. bytes to = 3; // The transactions index within the block. + // TODO: should this be uint32? to match the type from the native substream type? uint64 index = 4; } @@ -47,6 +48,26 @@ message Attribute { ChangeType change = 3; } +enum FinancialType{ + SWAP = 0; + LEND = 1; + LEVERAGE = 2; + PSM = 3; +} + + +enum ImplementationType { + VM = 0; + CUSTOM = 1; +} + +message ProtocolType{ + string name = 1; + FinancialType financial_type = 2; + repeated Attribute attribute_schema = 3; + ImplementationType implementation_type = 4; +} + // A struct describing a part of the protocol. // Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, // the component would represent a single contract. In case of VM integration, such component would @@ -67,6 +88,10 @@ message ProtocolComponent { repeated Attribute static_att = 4; // Type of change the component underwent. ChangeType change = 5; + /// Represents the functionality of the component. + ProtocolType protocol_type = 6; + // Transaction where this component was created + Transaction tx = 7; } // A struct for following the changes of Total Value Locked (TVL) of a protocol component. @@ -77,7 +102,7 @@ message BalanceChange { bytes token = 1; // The new balance of the token. bytes balance = 2; - // The id of the component whose TVL is tracked. + // The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. bytes component_id = 3; } diff --git a/substreams/ethereum-balancer/Cargo.lock b/substreams/ethereum-balancer/Cargo.lock index c96455e..b05dce5 100644 --- a/substreams/ethereum-balancer/Cargo.lock +++ b/substreams/ethereum-balancer/Cargo.lock @@ -884,24 +884,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "substreams-balancer" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytes", - "ethabi 18.0.0", - "getrandom", - "hex", - "hex-literal 0.4.1", - "itertools 0.12.0", - "num-bigint", - "prost 0.11.9", - "prost-types 0.12.3", - "substreams", - "substreams-ethereum", -] - [[package]] name = "substreams-ethereum" version = "0.9.9" @@ -933,6 +915,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "substreams-ethereum-balancer" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "ethabi 18.0.0", + "getrandom", + "hex", + "hex-literal 0.4.1", + "itertools 0.12.0", + "num-bigint", + "prost 0.11.9", + "prost-types 0.12.3", + "substreams", + "substreams-ethereum", +] + [[package]] name = "substreams-ethereum-core" version = "0.9.9" diff --git a/substreams/ethereum-balancer/proto/factory.proto b/substreams/ethereum-balancer/proto/factory.proto deleted file mode 100644 index f191ea8..0000000 --- a/substreams/ethereum-balancer/proto/factory.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; - -package eth.factory.v1; - -message Pools { - repeated Pool pools = 1; -} - -message Pool { - bytes pool_id = 1; - fixed64 log_ordinal = 2; -} - -message Transfer { - bytes from = 1; - bytes to = 2; - string token = 3; - string amount = 4; -} diff --git a/substreams/ethereum-balancer/proto/pool.proto b/substreams/ethereum-balancer/proto/pool.proto deleted file mode 100644 index c4dd94c..0000000 --- a/substreams/ethereum-balancer/proto/pool.proto +++ /dev/null @@ -1,15 +0,0 @@ -syntax = "proto3"; - -package eth.pool.v1; - -message Transfers { - repeated Transfer transfers = 1; -} - -message Transfer { - string from = 1; - string to = 2; - uint64 token_id = 3; - string trx_hash = 4; - uint64 ordinal = 5; -} diff --git a/substreams/ethereum-balancer/proto/tycho/evm/v1/common.proto b/substreams/ethereum-balancer/proto/tycho/evm/v1/common.proto deleted file mode 100644 index 1a5caf4..0000000 --- a/substreams/ethereum-balancer/proto/tycho/evm/v1/common.proto +++ /dev/null @@ -1,113 +0,0 @@ -syntax = "proto3"; - -package tycho.evm.v1; - -// This file contains the proto definitions for Substreams common to all integrations. - -// A struct describing a block. -message Block { - // The blocks hash. - bytes hash = 1; - // The parent blocks hash. - bytes parent_hash = 2; - // The block number. - uint64 number = 3; - // The block timestamp. - uint64 ts = 4; -} - -// A struct describing a transaction. -message Transaction { - // The transaction hash. - bytes hash = 1; - // The sender of the transaction. - bytes from = 2; - // The receiver of the transaction. - bytes to = 3; - // The transactions index within the block. - // TODO: should this be uint32? to match the type from the native substream type? - uint64 index = 4; -} - -// Enum to specify the type of a change. -enum ChangeType { - CHANGE_TYPE_UNSPECIFIED = 0; - CHANGE_TYPE_UPDATE = 1; - CHANGE_TYPE_CREATION = 2; - CHANGE_TYPE_DELETION = 3; -} - -// A custom struct representing an arbitrary attribute of a protocol component. -// This is mainly used by the native integration to track the necessary information about the protocol. -message Attribute { - // The name of the attribute. - string name = 1; - // The value of the attribute. - bytes value = 2; - // The type of change the attribute underwent. - ChangeType change = 3; -} - -// A struct describing a part of the protocol. -// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, -// the component would represent a single contract. In case of VM integration, such component would -// not need any attributes, because all the relevant info would be tracked via storage slots and balance changes. -// It can also be a wrapping contract, like WETH, that has a constant price, but it allows swapping tokens. -// This is why the name ProtocolComponent is used instead of "Pool" or "Pair". -message ProtocolComponent { - // A unique identifier for the component within the protocol. - // Can be e.g. a stringified address or a string describing the trading pair. - string id = 1; - // Addresses of the ERC20 tokens used by the component. - repeated bytes tokens = 2; - // Addresses of the contracts used by the component. - // Usually it is a single contract, but some protocols use multiple contracts. - repeated bytes contracts = 3; - // Attributes of the component. Used mainly be the native integration. - // The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. - repeated Attribute static_att = 4; - // Type of change the component underwent. - ChangeType change = 5; -} - -message TransactionProtocolComponents { - Transaction tx = 1; - repeated ProtocolComponent components = 2; -} - -message GroupedTransactionProtocolComponents { - repeated TransactionProtocolComponents tx_components = 1; -} - -// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. -message BalanceChange { - // The address of the ERC20 token whose balance changed. - bytes token = 1; - // The new balance of the token. - bytes balance = 2; - // The id of the component whose TVL is tracked. - // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - bytes component_id = 3; -} - -// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. -message BalanceDelta { - uint64 ord = 1; - // The tx hash of the transaction that caused the balance change. - Transaction tx = 2; - // The address of the ERC20 token whose balance changed. - bytes token = 3; - // The delta balance of the token. - bytes delta = 4; - // The id of the component whose TVL is tracked. - // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - bytes component_id = 5; -} - -message BalanceDeltas { - repeated BalanceDelta balance_deltas = 1; -} diff --git a/substreams/ethereum-balancer/proto/tycho/evm/v1/entity.proto b/substreams/ethereum-balancer/proto/tycho/evm/v1/entity.proto deleted file mode 100644 index 14539e4..0000000 --- a/substreams/ethereum-balancer/proto/tycho/evm/v1/entity.proto +++ /dev/null @@ -1,32 +0,0 @@ -syntax = "proto3"; - -package tycho.evm.v1; - -import "tycho/evm/v1/common.proto"; - -// This file contains the definition for the native integration of Substreams. - -// A component is a set of attributes that are associated with a custom entity. -message EntityChanges { - // A unique identifier of the entity within the protocol. - string component_id = 1; - // The set of attributes that are associated with the entity. - repeated Attribute attributes = 2; -} - -message TransactionEntityChanges { - Transaction tx = 1; - repeated EntityChanges entity_changes = 2; - // An array of newly added components. - repeated ProtocolComponent component_changes = 3; - // An array of balance changes to components. - repeated BalanceChange balance_changes = 4; -} - -// A set of transaction changes within a single block. -message BlockEntityChanges { - // The block for which these changes are collectively computed. - Block block = 1; - // The set of transaction changes observed in the specified block. - repeated TransactionEntityChanges changes = 2; -} diff --git a/substreams/ethereum-balancer/proto/tycho/evm/v1/vm.proto b/substreams/ethereum-balancer/proto/tycho/evm/v1/vm.proto deleted file mode 100644 index a49dcf0..0000000 --- a/substreams/ethereum-balancer/proto/tycho/evm/v1/vm.proto +++ /dev/null @@ -1,50 +0,0 @@ -syntax = "proto3"; - -package tycho.evm.v1; - -import "tycho/evm/v1/common.proto"; - -// This file contains proto definitions specific to the VM integration. - -// A key value entry into contract storage. -message ContractSlot { - // A contract's storage slot. - bytes slot = 2; - // The new value for this storage slot. - bytes value = 3; -} - -// Changes made to a single contract's state. -message ContractChange { - // The contract's address - bytes address = 1; - // The new native balance of the contract, empty bytes indicates no change. - bytes balance = 2; - // The new code of the contract, empty bytes indicates no change. - bytes code = 3; - // The changes to this contract's slots, empty sequence indicates no change. - repeated ContractSlot slots = 4; - // Whether this is an update, a creation or a deletion. - ChangeType change = 5; -} - -// A set of changes aggregated by transaction. -message TransactionContractChanges { - // The transaction instance that results in the changes. - Transaction tx = 1; - // Contains the changes induced by the above transaction, aggregated on a per-contract basis. - // Must include changes to every contract that is tracked by all ProtocolComponents. - repeated ContractChange contract_changes = 2; - // An array of any component changes. - repeated ProtocolComponent component_changes = 3; - // An array of balance changes to components. - repeated BalanceChange balance_changes = 4; -} - -// A set of transaction changes within a single block. -message BlockContractChanges { - // The block for which these changes are collectively computed. - Block block = 1; - // The set of transaction changes observed in the specified block. - repeated TransactionContractChanges changes = 2; -} diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 2ac0f0e..d121c2d 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -17,6 +17,7 @@ use pb::tycho::evm::v1::{self as tycho}; use contract_changes::extract_contract_changes; +use crate::pb::tycho::evm::v1::{BalanceDeltas, GroupedTransactionProtocolComponents}; use crate::{abi, contract_changes, pb, pool_factories}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -50,6 +51,12 @@ pub fn map_pools_created( call.call.address.as_slice(), log, call.call, + &tycho::Transaction { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + }, )?) }) .collect::>(); @@ -156,8 +163,8 @@ pub fn store_balance_changes(deltas: tycho::BalanceDeltas, store: StoreAddBigInt #[substreams::handlers::map] pub fn map_changes( block: eth::v2::Block, - grouped_components: tycho::GroupedTransactionProtocolComponents, - deltas: tycho::BalanceDeltas, + grouped_components: GroupedTransactionProtocolComponents, + deltas: BalanceDeltas, components_store: StoreGetInt64, balance_store: StoreDeltas, // Note, this map module is using the `deltas` mode for the store. ) -> Result { diff --git a/substreams/ethereum-balancer/src/pb/eth.balancer.v1.rs b/substreams/ethereum-balancer/src/pb/eth.balancer.v1.rs deleted file mode 100644 index 47065d4..0000000 --- a/substreams/ethereum-balancer/src/pb/eth.balancer.v1.rs +++ /dev/null @@ -1,28 +0,0 @@ -// @generated -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Pools { - #[prost(message, repeated, tag="1")] - pub pools: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Pool { - #[prost(bytes="vec", tag="1")] - pub pool_id: ::prost::alloc::vec::Vec, - #[prost(fixed64, tag="2")] - pub log_ordinal: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transfer { - #[prost(bytes="vec", tag="1")] - pub from: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="2")] - pub to: ::prost::alloc::vec::Vec, - #[prost(string, tag="3")] - pub token: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub amount: ::prost::alloc::string::String, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pb/eth.factory.v1.rs b/substreams/ethereum-balancer/src/pb/eth.factory.v1.rs deleted file mode 100644 index 47065d4..0000000 --- a/substreams/ethereum-balancer/src/pb/eth.factory.v1.rs +++ /dev/null @@ -1,28 +0,0 @@ -// @generated -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Pools { - #[prost(message, repeated, tag="1")] - pub pools: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Pool { - #[prost(bytes="vec", tag="1")] - pub pool_id: ::prost::alloc::vec::Vec, - #[prost(fixed64, tag="2")] - pub log_ordinal: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transfer { - #[prost(bytes="vec", tag="1")] - pub from: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="2")] - pub to: ::prost::alloc::vec::Vec, - #[prost(string, tag="3")] - pub token: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub amount: ::prost::alloc::string::String, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pb/eth.pool.v1.rs b/substreams/ethereum-balancer/src/pb/eth.pool.v1.rs deleted file mode 100644 index 16ad6e5..0000000 --- a/substreams/ethereum-balancer/src/pb/eth.pool.v1.rs +++ /dev/null @@ -1,22 +0,0 @@ -// @generated -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transfers { - #[prost(message, repeated, tag="1")] - pub transfers: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transfer { - #[prost(string, tag="1")] - pub from: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub to: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub token_id: u64, - #[prost(string, tag="4")] - pub trx_hash: ::prost::alloc::string::String, - #[prost(uint64, tag="5")] - pub ordinal: u64, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs index affc411..21d371d 100644 --- a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs +++ b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs @@ -51,6 +51,18 @@ pub struct Attribute { #[prost(enumeration="ChangeType", tag="3")] pub change: i32, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProtocolType { + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + #[prost(enumeration="FinancialType", tag="2")] + pub financial_type: i32, + #[prost(message, repeated, tag="3")] + pub attribute_schema: ::prost::alloc::vec::Vec, + #[prost(enumeration="ImplementationType", tag="4")] + pub implementation_type: i32, +} /// A struct describing a part of the protocol. /// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, /// the component would represent a single contract. In case of VM integration, such component would @@ -78,20 +90,12 @@ pub struct ProtocolComponent { /// Type of change the component underwent. #[prost(enumeration="ChangeType", tag="5")] pub change: i32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionProtocolComponents { - #[prost(message, optional, tag="1")] + /// / Represents the functionality of the component. + #[prost(message, optional, tag="6")] + pub protocol_type: ::core::option::Option, + /// Transaction where this component was created + #[prost(message, optional, tag="7")] pub tx: ::core::option::Option, - #[prost(message, repeated, tag="2")] - pub components: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GroupedTransactionProtocolComponents { - #[prost(message, repeated, tag="1")] - pub tx_components: ::prost::alloc::vec::Vec, } /// A struct for following the changes of Total Value Locked (TVL) of a protocol component. /// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. @@ -105,39 +109,11 @@ pub struct BalanceChange { /// The new balance of the token. #[prost(bytes="vec", tag="2")] pub balance: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. + /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. #[prost(bytes="vec", tag="3")] pub component_id: ::prost::alloc::vec::Vec, } -/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -/// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDelta { - #[prost(uint64, tag="1")] - pub ord: u64, - /// The tx hash of the transaction that caused the balance change. - #[prost(message, optional, tag="2")] - pub tx: ::core::option::Option, - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="3")] - pub token: ::prost::alloc::vec::Vec, - /// The delta balance of the token. - #[prost(bytes="vec", tag="4")] - pub delta: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - #[prost(bytes="vec", tag="5")] - pub component_id: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDeltas { - #[prost(message, repeated, tag="1")] - pub balance_deltas: ::prost::alloc::vec::Vec, -} /// Enum to specify the type of a change. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -171,6 +147,64 @@ impl ChangeType { } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FinancialType { + Swap = 0, + Lend = 1, + Leverage = 2, + Psm = 3, +} +impl FinancialType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FinancialType::Swap => "SWAP", + FinancialType::Lend => "LEND", + FinancialType::Leverage => "LEVERAGE", + FinancialType::Psm => "PSM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SWAP" => Some(Self::Swap), + "LEND" => Some(Self::Lend), + "LEVERAGE" => Some(Self::Leverage), + "PSM" => Some(Self::Psm), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ImplementationType { + Vm = 0, + Custom = 1, +} +impl ImplementationType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ImplementationType::Vm => "VM", + ImplementationType::Custom => "CUSTOM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VM" => Some(Self::Vm), + "CUSTOM" => Some(Self::Custom), + _ => None, + } + } +} // This file contains proto definitions specific to the VM integration. /// A key value entry into contract storage. @@ -233,4 +267,44 @@ pub struct BlockContractChanges { #[prost(message, repeated, tag="2")] pub changes: ::prost::alloc::vec::Vec, } +/// A struct for following the changes of Total Value Locked (TVL). +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDelta { + #[prost(uint64, tag="1")] + pub ord: u64, + /// The tx hash of the transaction that caused the balance change. + #[prost(message, optional, tag="2")] + pub tx: ::core::option::Option, + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="3")] + pub token: ::prost::alloc::vec::Vec, + /// The delta balance of the token. + #[prost(bytes="vec", tag="4")] + pub delta: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. + /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="5")] + pub component_id: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDeltas { + #[prost(message, repeated, tag="1")] + pub balance_deltas: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionProtocolComponents { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub components: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GroupedTransactionProtocolComponents { + #[prost(message, repeated, tag="1")] + pub tx_components: ::prost::alloc::vec::Vec, +} // @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index 62f1601..fb99696 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -3,6 +3,7 @@ use substreams_ethereum::{Event, Function}; use crate::abi; use crate::pb; +use crate::pb::tycho::evm::v1::{FinancialType, ImplementationType, ProtocolType, Transaction}; use pb::tycho::evm::v1::{self as tycho}; use substreams::hex; @@ -13,6 +14,7 @@ use substreams::scalar::BigInt; /// handled by any downstream application. trait SerializableVecBigInt { fn serialize_bytes(&self) -> Vec; + #[allow(dead_code)] fn deserialize_bytes(bytes: &[u8]) -> Vec; } @@ -25,7 +27,7 @@ impl SerializableVecBigInt for Vec { fn deserialize_bytes(bytes: &[u8]) -> Vec { bytes .chunks_exact(32) - .map(|chunk| BigInt::from_signed_bytes_be(chunk)) + .map(BigInt::from_signed_bytes_be) .collect::>() } } @@ -45,6 +47,7 @@ pub fn address_map( pool_factory_address: &[u8], log: &Log, call: &Call, + tx: &Transaction, ) -> Option { match *pool_factory_address { hex!("897888115Ada5773E02aA29F775430BFB5F34c51") => { @@ -70,6 +73,13 @@ pub fn address_map( }, ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } hex!("DB8d758BCb971e482B2C45f7F8a7740283A1bd3A") => { @@ -82,14 +92,19 @@ pub fn address_map( id: hex::encode(&pool_created.pool), tokens: create_call.tokens, contracts: vec![pool_factory_address.into(), pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "ComposableStablePoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - ], + static_att: vec![tycho::Attribute { + name: "pool_type".into(), + value: "ComposableStablePoolFactory".into(), + change: tycho::ChangeType::Creation.into(), + }], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } hex!("813EE7a840CE909E7Fea2117A44a90b8063bd4fd") => { @@ -117,6 +132,13 @@ pub fn address_map( // Note, rate provider might be provided as `create.protocol_id`, but as a BigInt. needs investigation ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } hex!("5F43FBa61f63Fa6bFF101a0A0458cEA917f6B347") => { @@ -142,6 +164,13 @@ pub fn address_map( }, ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } // ❌ Reading the deployed factory for Gearbox showcases that it's currently disabled @@ -214,6 +243,13 @@ pub fn address_map( }, ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } hex!("5F5222Ffa40F2AEd6380D022184D6ea67C776eE0") => { @@ -239,6 +275,13 @@ pub fn address_map( }, ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } // The `WeightedPool2TokenFactory` is a deprecated contract but we've included it since one @@ -266,6 +309,13 @@ pub fn address_map( }, ], change: tycho::ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "balancer".to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: ImplementationType::Vm.into(), + }), + tx: Some(tx.clone()), }) } _ => None, diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index f1bc3af..9919f23 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -7,9 +7,9 @@ protobuf: files: - tycho/evm/v1/vm.proto - tycho/evm/v1/common.proto + - tycho/evm/v1/balancer.proto importPaths: - - ../../proto/tycho/evm/v1/ - - ./proto + - ../../proto binaries: default: From 51275f0ccfba5caa43ca72c7d90ad4a193e1edc5 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:46:52 +0100 Subject: [PATCH 04/37] fix: remove balancer factory from components' contracts --- substreams/ethereum-balancer/src/modules.rs | 5 ++-- .../ethereum-balancer/src/pool_factories.rs | 28 +++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index d121c2d..e741fb3 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -47,7 +47,7 @@ pub fn map_pools_created( .logs_with_calls() .filter(|(_, call)| !call.call.state_reverted) .filter_map(|(log, call)| { - Some(pool_factories::address_map( + pool_factories::address_map( call.call.address.as_slice(), log, call.call, @@ -57,7 +57,7 @@ pub fn map_pools_created( to: tx.to.clone(), index: tx.index.into(), }, - )?) + ) }) .collect::>(); @@ -204,6 +204,7 @@ pub fn map_changes( .map(|(store_delta, balance_delta)| { let pool_id = key::segment_at(&store_delta.key, 1); let token_id = key::segment_at(&store_delta.key, 3); + ( balance_delta.tx.unwrap(), tycho::BalanceChange { diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index fb99696..e19933c 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -59,7 +59,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: create_call.tokens, - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -74,7 +74,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -91,7 +91,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: create_call.tokens, - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![tycho::Attribute { name: "pool_type".into(), value: "ComposableStablePoolFactory".into(), @@ -99,7 +99,7 @@ pub fn address_map( }], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -116,7 +116,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -133,7 +133,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -150,7 +150,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -165,7 +165,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -229,7 +229,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -244,7 +244,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -261,7 +261,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -276,7 +276,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), @@ -295,7 +295,7 @@ pub fn address_map( Some(tycho::ProtocolComponent { id: hex::encode(&pool_created.pool), tokens: create_call.tokens, - contracts: vec![pool_factory_address.into(), pool_created.pool], + contracts: vec![pool_created.pool], static_att: vec![ tycho::Attribute { name: "pool_type".into(), @@ -310,7 +310,7 @@ pub fn address_map( ], change: tycho::ChangeType::Creation.into(), protocol_type: Some(ProtocolType { - name: "balancer".to_string(), + name: "balancer_pool".to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Vm.into(), From accfa074fd9ccfaedf387891eb16c38b400889a9 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:50:12 +0100 Subject: [PATCH 05/37] fix: filter out changes that aren't balancer related --- .../ethereum-balancer/src/contract_changes.rs | 153 ++++++++++-------- 1 file changed, 87 insertions(+), 66 deletions(-) diff --git a/substreams/ethereum-balancer/src/contract_changes.rs b/substreams/ethereum-balancer/src/contract_changes.rs index 4ab49fe..664b0e7 100644 --- a/substreams/ethereum-balancer/src/contract_changes.rs +++ b/substreams/ethereum-balancer/src/contract_changes.rs @@ -97,77 +97,98 @@ pub fn extract_contract_changes( balance_changes.sort_unstable_by_key(|change| change.ordinal); code_changes.sort_unstable_by_key(|change| change.ordinal); - storage_changes.iter().for_each(|storage_change| { - let contract_change = changed_contracts - .entry(storage_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: storage_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&storage_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); + storage_changes + .iter() + .filter(|changes| { + contracts + .get_last(format!("pool:{0}", hex::encode(&changes.address))) + .is_some() + }) + .for_each(|storage_change| { + let contract_change = changed_contracts + .entry(storage_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: storage_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&storage_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); - let slot_value = contract_change - .slots - .entry(storage_change.key.clone()) - .or_insert_with(|| SlotValue { - new_value: storage_change.new_value.clone(), - start_value: storage_change.old_value.clone(), - }); + let slot_value = contract_change + .slots + .entry(storage_change.key.clone()) + .or_insert_with(|| SlotValue { + new_value: storage_change.new_value.clone(), + start_value: storage_change.old_value.clone(), + }); - slot_value - .new_value - .copy_from_slice(&storage_change.new_value); - }); + slot_value + .new_value + .copy_from_slice(&storage_change.new_value); + }); - balance_changes.iter().for_each(|balance_change| { - let contract_change = changed_contracts - .entry(balance_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: balance_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&balance_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); + balance_changes + .iter() + .filter(|changes| { + contracts + .get_last(format!("pool:{0}", hex::encode(&changes.address))) + .is_some() + }) + .for_each(|balance_change| { + let contract_change = changed_contracts + .entry(balance_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: balance_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&balance_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); - if let Some(new_balance) = &balance_change.new_value { - contract_change.balance.clear(); + if let Some(new_balance) = &balance_change.new_value { + contract_change.balance.clear(); + contract_change + .balance + .extend_from_slice(&new_balance.bytes); + } + }); + + code_changes + .iter() + .filter(|changes| { + contracts + .get_last(format!("pool:{0}", hex::encode(&changes.address))) + .is_some() + }) + .for_each(|code_change| { + let contract_change = changed_contracts + .entry(code_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: code_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&code_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); + + contract_change.code.clear(); contract_change - .balance - .extend_from_slice(&new_balance.bytes); - } - }); - - code_changes.iter().for_each(|code_change| { - let contract_change = changed_contracts - .entry(code_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: code_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&code_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); - - contract_change.code.clear(); - contract_change - .code - .extend_from_slice(&code_change.new_code); - }); + .code + .extend_from_slice(&code_change.new_code); + }); if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() { transaction_contract_changes From c283a8134112b502a874e8c76bf63999bdc1e7ce Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Mon, 11 Mar 2024 18:32:42 +0100 Subject: [PATCH 06/37] Make clippy happy --- substreams/ethereum-balancer/build.rs | 1 + substreams/ethereum-balancer/src/abi/mod.rs | 1 + substreams/ethereum-balancer/src/modules.rs | 11 +++-------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/substreams/ethereum-balancer/build.rs b/substreams/ethereum-balancer/build.rs index ceabf48..90e1f1e 100644 --- a/substreams/ethereum-balancer/build.rs +++ b/substreams/ethereum-balancer/build.rs @@ -8,6 +8,7 @@ fn main() -> Result<()> { let files = fs::read_dir(abi_folder)?; let mut mod_rs_content = String::new(); + mod_rs_content.push_str("#![allow(clippy::all)]\n"); for file in files { let file = file?; diff --git a/substreams/ethereum-balancer/src/abi/mod.rs b/substreams/ethereum-balancer/src/abi/mod.rs index ef6622d..0f60dc0 100644 --- a/substreams/ethereum-balancer/src/abi/mod.rs +++ b/substreams/ethereum-balancer/src/abi/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::all)] pub mod yearn_linear_pool_factory; pub mod composable_stable_pool_factory; pub mod vault; diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index e741fb3..7d666cc 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -102,7 +102,7 @@ pub fn map_balance_deltas( ) -> Result { Ok(tycho::BalanceDeltas { balance_deltas: block - .events::(&[&VAULT_ADDRESS]) + .events::(&[VAULT_ADDRESS]) .flat_map(|(event, log)| { event .tokens @@ -111,12 +111,7 @@ pub fn map_balance_deltas( .filter_map(|(token, delta)| { let component_id: Vec<_> = event.pool_id.into(); - if store - .get_last(format!("pool:{0}", hex::encode(&component_id))) - .is_none() - { - return None; - } + store.get_last(format!("pool:{0}", hex::encode(&component_id)))?; Some(tycho::BalanceDelta { ord: log.log.ordinal, @@ -253,7 +248,7 @@ pub fn map_changes( }), changes: transaction_contract_changes .drain() - .sorted_unstable_by_key(|(index, _)| index.clone()) + .sorted_unstable_by_key(|(index, _)| *index) .filter_map(|(_, change)| { if change.contract_changes.is_empty() && change.component_changes.is_empty() From a1864e3cd4bb09dfda2f25d4ce2887e9646e8cb5 Mon Sep 17 00:00:00 2001 From: kayibal Date: Mon, 11 Mar 2024 19:10:28 +0000 Subject: [PATCH 07/37] Don't include balancer specific pb in tycho pbs. --- .../ethereum-balancer/proto}/balancer.proto | 8 ++-- substreams/ethereum-balancer/src/modules.rs | 18 ++++---- .../ethereum-balancer/src/pb/balancer.rs | 42 +++++++++++++++++++ substreams/ethereum-balancer/src/pb/mod.rs | 5 +++ .../ethereum-balancer/src/pb/tycho.evm.v1.rs | 40 ------------------ substreams/ethereum-balancer/substreams.yaml | 3 +- 6 files changed, 62 insertions(+), 54 deletions(-) rename {proto/tycho/evm/v1 => substreams/ethereum-balancer/proto}/balancer.proto (84%) create mode 100644 substreams/ethereum-balancer/src/pb/balancer.rs diff --git a/proto/tycho/evm/v1/balancer.proto b/substreams/ethereum-balancer/proto/balancer.proto similarity index 84% rename from proto/tycho/evm/v1/balancer.proto rename to substreams/ethereum-balancer/proto/balancer.proto index f5a4c63..6efe1c9 100644 --- a/proto/tycho/evm/v1/balancer.proto +++ b/substreams/ethereum-balancer/proto/balancer.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package tycho.evm.v1; +package balancer; import "tycho/evm/v1/common.proto"; @@ -8,7 +8,7 @@ import "tycho/evm/v1/common.proto"; message BalanceDelta { uint64 ord = 1; // The tx hash of the transaction that caused the balance change. - Transaction tx = 2; + tycho.evm.v1.Transaction tx = 2; // The address of the ERC20 token whose balance changed. bytes token = 3; // The delta balance of the token. @@ -23,8 +23,8 @@ message BalanceDeltas { } message TransactionProtocolComponents { - Transaction tx = 1; - repeated ProtocolComponent components = 2; + tycho.evm.v1.Transaction tx = 1; + repeated tycho.evm.v1.ProtocolComponent components = 2; } message GroupedTransactionProtocolComponents { diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 7d666cc..96554ca 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -17,7 +17,7 @@ use pb::tycho::evm::v1::{self as tycho}; use contract_changes::extract_contract_changes; -use crate::pb::tycho::evm::v1::{BalanceDeltas, GroupedTransactionProtocolComponents}; +use crate::pb::balancer::{BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, TransactionProtocolComponents}; use crate::{abi, contract_changes, pb, pool_factories}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -36,10 +36,10 @@ impl PartialEq for TransactionWrapper { #[substreams::handlers::map] pub fn map_pools_created( block: eth::v2::Block, -) -> Result { +) -> 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(tycho::GroupedTransactionProtocolComponents { + Ok(GroupedTransactionProtocolComponents { tx_components: block .transactions() .filter_map(|tx| { @@ -62,7 +62,7 @@ pub fn map_pools_created( .collect::>(); if !components.is_empty() { - Some(tycho::TransactionProtocolComponents { + Some(TransactionProtocolComponents { tx: Some(tycho::Transaction { hash: tx.hash.clone(), from: tx.from.clone(), @@ -81,7 +81,7 @@ pub fn map_pools_created( /// Simply stores the `ProtocolComponent`s with the pool id as the key #[substreams::handlers::store] -pub fn store_pools_created(map: tycho::GroupedTransactionProtocolComponents, store: StoreAddInt64) { +pub fn store_pools_created(map: GroupedTransactionProtocolComponents, store: StoreAddInt64) { store.add_many( 0, &map.tx_components @@ -99,8 +99,8 @@ pub fn store_pools_created(map: tycho::GroupedTransactionProtocolComponents, sto pub fn map_balance_deltas( block: eth::v2::Block, store: StoreGetInt64, -) -> Result { - Ok(tycho::BalanceDeltas { +) -> Result { + Ok(BalanceDeltas { balance_deltas: block .events::(&[VAULT_ADDRESS]) .flat_map(|(event, log)| { @@ -113,7 +113,7 @@ pub fn map_balance_deltas( store.get_last(format!("pool:{0}", hex::encode(&component_id)))?; - Some(tycho::BalanceDelta { + Some(BalanceDelta { ord: log.log.ordinal, tx: Some(tycho::Transaction { hash: log.receipt.transaction.hash.clone(), @@ -135,7 +135,7 @@ pub fn map_balance_deltas( /// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the /// store key to ensure that there's a unique balance being tallied for each. #[substreams::handlers::store] -pub fn store_balance_changes(deltas: tycho::BalanceDeltas, store: StoreAddBigInt) { +pub fn store_balance_changes(deltas: BalanceDeltas, store: StoreAddBigInt) { deltas.balance_deltas.iter().for_each(|delta| { store.add( delta.ord, diff --git a/substreams/ethereum-balancer/src/pb/balancer.rs b/substreams/ethereum-balancer/src/pb/balancer.rs new file mode 100644 index 0000000..b2f52d2 --- /dev/null +++ b/substreams/ethereum-balancer/src/pb/balancer.rs @@ -0,0 +1,42 @@ +// @generated +/// A struct for following the changes of Total Value Locked (TVL). +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDelta { + #[prost(uint64, tag="1")] + pub ord: u64, + /// The tx hash of the transaction that caused the balance change. + #[prost(message, optional, tag="2")] + pub tx: ::core::option::Option, + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="3")] + pub token: ::prost::alloc::vec::Vec, + /// The delta balance of the token. + #[prost(bytes="vec", tag="4")] + pub delta: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. + /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="5")] + pub component_id: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDeltas { + #[prost(message, repeated, tag="1")] + pub balance_deltas: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionProtocolComponents { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub components: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GroupedTransactionProtocolComponents { + #[prost(message, repeated, tag="1")] + pub tx_components: ::prost::alloc::vec::Vec, +} +// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pb/mod.rs b/substreams/ethereum-balancer/src/pb/mod.rs index 43d8838..1d5f1e8 100644 --- a/substreams/ethereum-balancer/src/pb/mod.rs +++ b/substreams/ethereum-balancer/src/pb/mod.rs @@ -1,4 +1,9 @@ // @generated +// @@protoc_insertion_point(attribute:balancer) +pub mod balancer { + include!("balancer.rs"); + // @@protoc_insertion_point(balancer) +} pub mod tycho { pub mod evm { // @@protoc_insertion_point(attribute:tycho.evm.v1) diff --git a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs index 21d371d..cf81ed2 100644 --- a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs +++ b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs @@ -267,44 +267,4 @@ pub struct BlockContractChanges { #[prost(message, repeated, tag="2")] pub changes: ::prost::alloc::vec::Vec, } -/// A struct for following the changes of Total Value Locked (TVL). -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDelta { - #[prost(uint64, tag="1")] - pub ord: u64, - /// The tx hash of the transaction that caused the balance change. - #[prost(message, optional, tag="2")] - pub tx: ::core::option::Option, - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="3")] - pub token: ::prost::alloc::vec::Vec, - /// The delta balance of the token. - #[prost(bytes="vec", tag="4")] - pub delta: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - #[prost(bytes="vec", tag="5")] - pub component_id: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDeltas { - #[prost(message, repeated, tag="1")] - pub balance_deltas: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionProtocolComponents { - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - #[prost(message, repeated, tag="2")] - pub components: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GroupedTransactionProtocolComponents { - #[prost(message, repeated, tag="1")] - pub tx_components: ::prost::alloc::vec::Vec, -} // @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 9919f23..c5b56d0 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -7,9 +7,10 @@ protobuf: files: - tycho/evm/v1/vm.proto - tycho/evm/v1/common.proto - - tycho/evm/v1/balancer.proto + - balancer.proto importPaths: - ../../proto + - ./proto binaries: default: From 1e546230ded47e52096b6a7ec84fa1f175c7a9b9 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:49:09 +0100 Subject: [PATCH 08/37] fix: map_balance_deltas pool_id check --- substreams/ethereum-balancer/src/modules.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 96554ca..8448772 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -17,7 +17,10 @@ use pb::tycho::evm::v1::{self as tycho}; use contract_changes::extract_contract_changes; -use crate::pb::balancer::{BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, TransactionProtocolComponents}; +use crate::pb::balancer::{ + BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, + TransactionProtocolComponents, +}; use crate::{abi, contract_changes, pb, pool_factories}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -34,9 +37,7 @@ impl PartialEq for TransactionWrapper { } #[substreams::handlers::map] -pub fn map_pools_created( - block: eth::v2::Block, -) -> Result { +pub fn map_pools_created(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(GroupedTransactionProtocolComponents { @@ -109,7 +110,7 @@ pub fn map_balance_deltas( .iter() .zip(event.deltas.iter()) .filter_map(|(token, delta)| { - let component_id: Vec<_> = event.pool_id.into(); + let component_id = event.pool_id[..20].to_vec(); store.get_last(format!("pool:{0}", hex::encode(&component_id)))?; @@ -119,11 +120,11 @@ pub fn map_balance_deltas( hash: log.receipt.transaction.hash.clone(), from: log.receipt.transaction.from.clone(), to: log.receipt.transaction.to.clone(), - index: Into::::into(log.receipt.transaction.index), + index: log.receipt.transaction.index.into(), }), - token: token.clone(), + token: token.to_vec(), delta: delta.to_signed_bytes_be(), - component_id: component_id.clone(), + component_id, }) }) .collect::>() From 38dcd9d843354bfc8fdb9e461da4594d102837e1 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:51:26 +0100 Subject: [PATCH 09/37] fix: BalanceChange encoding --- proto/tycho/evm/v1/common.proto | 2 +- substreams/ethereum-balancer/src/modules.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/proto/tycho/evm/v1/common.proto b/proto/tycho/evm/v1/common.proto index 545cad0..7f6d369 100644 --- a/proto/tycho/evm/v1/common.proto +++ b/proto/tycho/evm/v1/common.proto @@ -100,7 +100,7 @@ message ProtocolComponent { message BalanceChange { // The address of the ERC20 token whose balance changed. bytes token = 1; - // The new balance of the token. + // The new balance of the token. Note: it must be a big endian encoded int. bytes balance = 2; // The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 8448772..f84a496 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::str::FromStr; use anyhow::Result; use substreams::hex; @@ -200,12 +201,17 @@ pub fn map_changes( .map(|(store_delta, balance_delta)| { let pool_id = key::segment_at(&store_delta.key, 1); let token_id = key::segment_at(&store_delta.key, 3); + // store_delta.new_value is an ASCII string representing an integer + let ascii_string = + String::from_utf8(store_delta.new_value.clone()).expect("Invalid UTF-8 sequence"); + let balance = BigInt::from_str(&ascii_string).expect("Failed to parse integer"); + let big_endian_bytes_balance = balance.to_bytes_be().1; ( balance_delta.tx.unwrap(), tycho::BalanceChange { token: hex::decode(token_id).expect("Token ID not valid hex"), - balance: store_delta.new_value, + balance: big_endian_bytes_balance, component_id: hex::decode(pool_id).expect("Token ID not valid hex"), }, ) From 2a1b83f6c5c317ac5e2f270904e9f944c9668f09 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:53:30 +0100 Subject: [PATCH 10/37] fix: index balance changes from `Swap` events --- substreams/ethereum-balancer/src/modules.rs | 90 +++++++++++++++------ 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index f84a496..71f0e83 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -17,6 +17,7 @@ use itertools::Itertools; use pb::tycho::evm::v1::{self as tycho}; use contract_changes::extract_contract_changes; +use substreams_ethereum::Event; use crate::pb::balancer::{ BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, @@ -95,43 +96,82 @@ pub fn store_pools_created(map: GroupedTransactionProtocolComponents, store: Sto ); } -/// Since the `PoolBalanceChanged` events administer only deltas, we need to leverage a map and a +/// Since the `PoolBalanceChanged` and `Swap` 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] pub fn map_balance_deltas( block: eth::v2::Block, store: StoreGetInt64, ) -> Result { - Ok(BalanceDeltas { - balance_deltas: block - .events::(&[VAULT_ADDRESS]) - .flat_map(|(event, log)| { - event - .tokens - .iter() - .zip(event.deltas.iter()) - .filter_map(|(token, delta)| { - let component_id = event.pool_id[..20].to_vec(); + let balance_deltas = block + .logs() + .filter(|log| log.address() == VAULT_ADDRESS) + .flat_map(|vault_log| { + let mut deltas = Vec::new(); - store.get_last(format!("pool:{0}", hex::encode(&component_id)))?; - - Some(BalanceDelta { - ord: log.log.ordinal, + if let Some(ev) = + abi::vault::events::PoolBalanceChanged::match_and_decode(vault_log.log) + { + let component_id = ev.pool_id[..20].to_vec(); + if store + .get_last(format!("pool:{}", hex::encode(&component_id))) + .is_some() + { + for (token, delta) in ev.tokens.iter().zip(ev.deltas.iter()) { + deltas.push(BalanceDelta { + ord: vault_log.ordinal(), tx: Some(tycho::Transaction { - hash: log.receipt.transaction.hash.clone(), - from: log.receipt.transaction.from.clone(), - to: log.receipt.transaction.to.clone(), - index: log.receipt.transaction.index.into(), + hash: vault_log.receipt.transaction.hash.clone(), + from: vault_log.receipt.transaction.from.clone(), + to: vault_log.receipt.transaction.to.clone(), + index: vault_log.receipt.transaction.index.into(), }), token: token.to_vec(), delta: delta.to_signed_bytes_be(), + component_id: component_id.clone(), + }); + } + } + } else if let Some(ev) = abi::vault::events::Swap::match_and_decode(vault_log.log) { + let component_id = ev.pool_id[..20].to_vec(); + if store + .get_last(format!("pool:{}", hex::encode(&component_id))) + .is_some() + { + deltas.extend_from_slice(&[ + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(tycho::Transaction { + hash: vault_log.receipt.transaction.hash.clone(), + from: vault_log.receipt.transaction.from.clone(), + to: vault_log.receipt.transaction.to.clone(), + index: vault_log.receipt.transaction.index.into(), + }), + token: ev.token_in.to_vec(), + delta: ev.amount_in.to_signed_bytes_be(), + component_id: component_id.clone(), + }, + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(tycho::Transaction { + hash: vault_log.receipt.transaction.hash.clone(), + from: vault_log.receipt.transaction.from.clone(), + to: vault_log.receipt.transaction.to.clone(), + index: vault_log.receipt.transaction.index.into(), + }), + token: ev.token_out.to_vec(), + delta: ev.amount_out.neg().to_signed_bytes_be(), component_id, - }) - }) - .collect::>() - }) - .collect::>(), - }) + }, + ]); + } + } + + deltas + }) + .collect::>(); + + Ok(BalanceDeltas { balance_deltas }) } /// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the From 7601072e873b21738c8238bb23016365ca4fc882 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:19:59 +0100 Subject: [PATCH 11/37] fix: encode component_id as UTF8 --- substreams/ethereum-balancer/src/modules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 71f0e83..2b47bd1 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -252,7 +252,7 @@ pub fn map_changes( tycho::BalanceChange { token: hex::decode(token_id).expect("Token ID not valid hex"), balance: big_endian_bytes_balance, - component_id: hex::decode(pool_id).expect("Token ID not valid hex"), + component_id: pool_id.as_bytes().to_vec(), }, ) }) From 4b2437dab63d320daa09711375d0cc879f0b3fad Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 12:11:38 +0000 Subject: [PATCH 12/37] Revert "Don't include balancer specific pb in tycho pbs." This reverts commit a1864e3c. We will actually make the balance delta messages part of the tycho packages since this makes a few things simpler when trying to factor out an sdk. --- .../tycho/evm/v1}/balancer.proto | 8 ++-- substreams/ethereum-balancer/src/modules.rs | 10 ++--- .../ethereum-balancer/src/pb/balancer.rs | 42 ------------------- substreams/ethereum-balancer/src/pb/mod.rs | 5 --- .../ethereum-balancer/src/pb/tycho.evm.v1.rs | 40 ++++++++++++++++++ substreams/ethereum-balancer/substreams.yaml | 3 +- 6 files changed, 49 insertions(+), 59 deletions(-) rename {substreams/ethereum-balancer/proto => proto/tycho/evm/v1}/balancer.proto (84%) delete mode 100644 substreams/ethereum-balancer/src/pb/balancer.rs diff --git a/substreams/ethereum-balancer/proto/balancer.proto b/proto/tycho/evm/v1/balancer.proto similarity index 84% rename from substreams/ethereum-balancer/proto/balancer.proto rename to proto/tycho/evm/v1/balancer.proto index 6efe1c9..f5a4c63 100644 --- a/substreams/ethereum-balancer/proto/balancer.proto +++ b/proto/tycho/evm/v1/balancer.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package balancer; +package tycho.evm.v1; import "tycho/evm/v1/common.proto"; @@ -8,7 +8,7 @@ import "tycho/evm/v1/common.proto"; message BalanceDelta { uint64 ord = 1; // The tx hash of the transaction that caused the balance change. - tycho.evm.v1.Transaction tx = 2; + Transaction tx = 2; // The address of the ERC20 token whose balance changed. bytes token = 3; // The delta balance of the token. @@ -23,8 +23,8 @@ message BalanceDeltas { } message TransactionProtocolComponents { - tycho.evm.v1.Transaction tx = 1; - repeated tycho.evm.v1.ProtocolComponent components = 2; + Transaction tx = 1; + repeated ProtocolComponent components = 2; } message GroupedTransactionProtocolComponents { diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 2b47bd1..75f61a3 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -14,16 +14,14 @@ use substreams::scalar::BigInt; use substreams_ethereum::pb::eth; use itertools::Itertools; -use pb::tycho::evm::v1::{self as tycho}; + use contract_changes::extract_contract_changes; use substreams_ethereum::Event; -use crate::pb::balancer::{ - BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, - TransactionProtocolComponents, -}; -use crate::{abi, contract_changes, pb, pool_factories}; +use crate::pb::tycho::evm::v1::{self as tycho}; +use crate::pb::tycho::evm::v1::{BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, TransactionProtocolComponents}; +use crate::{abi, contract_changes, pool_factories}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); diff --git a/substreams/ethereum-balancer/src/pb/balancer.rs b/substreams/ethereum-balancer/src/pb/balancer.rs deleted file mode 100644 index b2f52d2..0000000 --- a/substreams/ethereum-balancer/src/pb/balancer.rs +++ /dev/null @@ -1,42 +0,0 @@ -// @generated -/// A struct for following the changes of Total Value Locked (TVL). -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDelta { - #[prost(uint64, tag="1")] - pub ord: u64, - /// The tx hash of the transaction that caused the balance change. - #[prost(message, optional, tag="2")] - pub tx: ::core::option::Option, - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="3")] - pub token: ::prost::alloc::vec::Vec, - /// The delta balance of the token. - #[prost(bytes="vec", tag="4")] - pub delta: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - #[prost(bytes="vec", tag="5")] - pub component_id: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDeltas { - #[prost(message, repeated, tag="1")] - pub balance_deltas: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionProtocolComponents { - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - #[prost(message, repeated, tag="2")] - pub components: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GroupedTransactionProtocolComponents { - #[prost(message, repeated, tag="1")] - pub tx_components: ::prost::alloc::vec::Vec, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pb/mod.rs b/substreams/ethereum-balancer/src/pb/mod.rs index 1d5f1e8..43d8838 100644 --- a/substreams/ethereum-balancer/src/pb/mod.rs +++ b/substreams/ethereum-balancer/src/pb/mod.rs @@ -1,9 +1,4 @@ // @generated -// @@protoc_insertion_point(attribute:balancer) -pub mod balancer { - include!("balancer.rs"); - // @@protoc_insertion_point(balancer) -} pub mod tycho { pub mod evm { // @@protoc_insertion_point(attribute:tycho.evm.v1) diff --git a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs index cf81ed2..21d371d 100644 --- a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs +++ b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs @@ -267,4 +267,44 @@ pub struct BlockContractChanges { #[prost(message, repeated, tag="2")] pub changes: ::prost::alloc::vec::Vec, } +/// A struct for following the changes of Total Value Locked (TVL). +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDelta { + #[prost(uint64, tag="1")] + pub ord: u64, + /// The tx hash of the transaction that caused the balance change. + #[prost(message, optional, tag="2")] + pub tx: ::core::option::Option, + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="3")] + pub token: ::prost::alloc::vec::Vec, + /// The delta balance of the token. + #[prost(bytes="vec", tag="4")] + pub delta: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. + /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="5")] + pub component_id: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDeltas { + #[prost(message, repeated, tag="1")] + pub balance_deltas: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionProtocolComponents { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub components: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GroupedTransactionProtocolComponents { + #[prost(message, repeated, tag="1")] + pub tx_components: ::prost::alloc::vec::Vec, +} // @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index c5b56d0..9919f23 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -7,10 +7,9 @@ protobuf: files: - tycho/evm/v1/vm.proto - tycho/evm/v1/common.proto - - balancer.proto + - tycho/evm/v1/balancer.proto importPaths: - ../../proto - - ./proto binaries: default: From 0d621a4545c9a00f6ce6942d127b4af259b33dec Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 12:28:10 +0000 Subject: [PATCH 13/37] Improve the naming of utils. --- .../evm/v1/{balancer.proto => utils.proto} | 17 ++++++++++++---- substreams/ethereum-balancer/src/modules.rs | 20 +++++++++---------- .../ethereum-balancer/src/pb/tycho.evm.v1.rs | 19 +++++++++++++----- substreams/ethereum-balancer/substreams.yaml | 2 +- 4 files changed, 38 insertions(+), 20 deletions(-) rename proto/tycho/evm/v1/{balancer.proto => utils.proto} (50%) diff --git a/proto/tycho/evm/v1/balancer.proto b/proto/tycho/evm/v1/utils.proto similarity index 50% rename from proto/tycho/evm/v1/balancer.proto rename to proto/tycho/evm/v1/utils.proto index f5a4c63..ea3f5d5 100644 --- a/proto/tycho/evm/v1/balancer.proto +++ b/proto/tycho/evm/v1/utils.proto @@ -4,8 +4,13 @@ package tycho.evm.v1; import "tycho/evm/v1/common.proto"; -// A struct for following the changes of Total Value Locked (TVL). +// A message containing relative balance changes. +// +// Used to track token balances of protocol components in case they are only +// available as relative values within a block. message BalanceDelta { + // The ordinal of the balance change. Must be unique & deterministic over all balances + // changes within a block. uint64 ord = 1; // The tx hash of the transaction that caused the balance change. Transaction tx = 2; @@ -14,19 +19,23 @@ message BalanceDelta { // The delta balance of the token. bytes delta = 4; // The id of the component whose TVL is tracked. - // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + // If the protocol component includes multiple contracts, the balance change must be + // aggregated to reflect how much tokens can be traded. bytes component_id = 5; } -message BalanceDeltas { +// A set of balances deltas, usually a group of changes within a single block. +message BlockBalanceDeltas { repeated BalanceDelta balance_deltas = 1; } +// A message containing protocol components that were created by a single tx. message TransactionProtocolComponents { Transaction tx = 1; repeated ProtocolComponent components = 2; } -message GroupedTransactionProtocolComponents { +// All protocol components that were created within a block with their corresponding tx. +message BlockTransactionProtocolComponents { repeated TransactionProtocolComponents tx_components = 1; } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 75f61a3..c4fcb4a 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -20,7 +20,7 @@ use contract_changes::extract_contract_changes; use substreams_ethereum::Event; use crate::pb::tycho::evm::v1::{self as tycho}; -use crate::pb::tycho::evm::v1::{BalanceDelta, BalanceDeltas, GroupedTransactionProtocolComponents, TransactionProtocolComponents}; +use crate::pb::tycho::evm::v1::{BalanceDelta, BlockBalanceDeltas, BlockTransactionProtocolComponents, TransactionProtocolComponents}; use crate::{abi, contract_changes, pool_factories}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -37,10 +37,10 @@ impl PartialEq for TransactionWrapper { } #[substreams::handlers::map] -pub fn map_pools_created(block: eth::v2::Block) -> Result { +pub fn map_pools_created(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(GroupedTransactionProtocolComponents { + Ok(BlockTransactionProtocolComponents { tx_components: block .transactions() .filter_map(|tx| { @@ -82,7 +82,7 @@ pub fn map_pools_created(block: eth::v2::Block) -> Result Result { +) -> Result { let balance_deltas = block .logs() .filter(|log| log.address() == VAULT_ADDRESS) @@ -169,13 +169,13 @@ pub fn map_balance_deltas( }) .collect::>(); - Ok(BalanceDeltas { balance_deltas }) + Ok(BlockBalanceDeltas { balance_deltas }) } /// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the /// store key to ensure that there's a unique balance being tallied for each. #[substreams::handlers::store] -pub fn store_balance_changes(deltas: BalanceDeltas, store: StoreAddBigInt) { +pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { deltas.balance_deltas.iter().for_each(|delta| { store.add( delta.ord, @@ -198,8 +198,8 @@ pub fn store_balance_changes(deltas: BalanceDeltas, store: StoreAddBigInt) { #[substreams::handlers::map] pub fn map_changes( block: eth::v2::Block, - grouped_components: GroupedTransactionProtocolComponents, - deltas: BalanceDeltas, + grouped_components: BlockTransactionProtocolComponents, + deltas: BlockBalanceDeltas, components_store: StoreGetInt64, balance_store: StoreDeltas, // Note, this map module is using the `deltas` mode for the store. ) -> Result { @@ -229,7 +229,7 @@ pub fn map_changes( }); // Balance changes are gathered by the `StoreDelta` based on `PoolBalanceChanged` creating - // `BalanceDeltas`. We essentially just process the changes that occured to the `store` this + // `BlockBalanceDeltas`. We essentially just process the changes that occured to the `store` this // block. Then, these balance changes are merged onto the existing map of tx contract changes, // inserting a new one if it doesn't exist. balance_store diff --git a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs index 21d371d..387ff7b 100644 --- a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs +++ b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs @@ -106,7 +106,7 @@ pub struct BalanceChange { /// The address of the ERC20 token whose balance changed. #[prost(bytes="vec", tag="1")] pub token: ::prost::alloc::vec::Vec, - /// The new balance of the token. + /// The new balance of the token. Note: it must be a big endian encoded int. #[prost(bytes="vec", tag="2")] pub balance: ::prost::alloc::vec::Vec, /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. @@ -267,10 +267,15 @@ pub struct BlockContractChanges { #[prost(message, repeated, tag="2")] pub changes: ::prost::alloc::vec::Vec, } -/// A struct for following the changes of Total Value Locked (TVL). +/// A message containing relative balance changes. +/// +/// Used to track token balances of protocol components in case they are only +/// available as relative values within a block. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct BalanceDelta { + /// The ordinal of the balance change. Must be unique & deterministic over all balances + /// changes within a block. #[prost(uint64, tag="1")] pub ord: u64, /// The tx hash of the transaction that caused the balance change. @@ -283,16 +288,19 @@ pub struct BalanceDelta { #[prost(bytes="vec", tag="4")] pub delta: ::prost::alloc::vec::Vec, /// The id of the component whose TVL is tracked. - /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + /// If the protocol component includes multiple contracts, the balance change must be + /// aggregated to reflect how much tokens can be traded. #[prost(bytes="vec", tag="5")] pub component_id: ::prost::alloc::vec::Vec, } +/// A set of balances deltas, usually a group of changes within a single block. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDeltas { +pub struct BlockBalanceDeltas { #[prost(message, repeated, tag="1")] pub balance_deltas: ::prost::alloc::vec::Vec, } +/// A message containing protocol components that were created by a single tx. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct TransactionProtocolComponents { @@ -301,9 +309,10 @@ pub struct TransactionProtocolComponents { #[prost(message, repeated, tag="2")] pub components: ::prost::alloc::vec::Vec, } +/// All protocol components that were created within a block with their corresponding tx. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct GroupedTransactionProtocolComponents { +pub struct BlockTransactionProtocolComponents { #[prost(message, repeated, tag="1")] pub tx_components: ::prost::alloc::vec::Vec, } diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 9919f23..66da244 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -7,7 +7,7 @@ protobuf: files: - tycho/evm/v1/vm.proto - tycho/evm/v1/common.proto - - tycho/evm/v1/balancer.proto + - tycho/evm/v1/utils.proto importPaths: - ../../proto From 92f20d0521dcd16c2ba11fc54d6f51c37873935e Mon Sep 17 00:00:00 2001 From: kayibal Date: Mon, 11 Mar 2024 20:08:10 +0000 Subject: [PATCH 14/37] Add shared tycho-substreams lib. --- crates/tycho-substreams/Cargo.lock | 1050 +++++++++++++++++ crates/tycho-substreams/Cargo.toml | 7 + crates/tycho-substreams/Readme.md | 18 + crates/tycho-substreams/buf.gen.yaml | 12 + crates/tycho-substreams/src/contract.rs | 199 ++++ crates/tycho-substreams/src/lib.rs | 2 + crates/tycho-substreams/src/pb/mod.rs | 10 + .../tycho-substreams/src/pb/tycho.evm.v1.rs | 309 +++++ 8 files changed, 1607 insertions(+) create mode 100644 crates/tycho-substreams/Cargo.lock create mode 100644 crates/tycho-substreams/Cargo.toml create mode 100644 crates/tycho-substreams/Readme.md create mode 100644 crates/tycho-substreams/buf.gen.yaml create mode 100644 crates/tycho-substreams/src/contract.rs create mode 100644 crates/tycho-substreams/src/lib.rs create mode 100644 crates/tycho-substreams/src/pb/mod.rs create mode 100644 crates/tycho-substreams/src/pb/tycho.evm.v1.rs diff --git a/crates/tycho-substreams/Cargo.lock b/crates/tycho-substreams/Cargo.lock new file mode 100644 index 0000000..5e61c4a --- /dev/null +++ b/crates/tycho-substreams/Cargo.lock @@ -0,0 +1,1050 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "ethabi" +version = "17.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pad" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "primitive-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "substreams" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3520661f782c338f0e3c6cfc001ac790ed5e68d8f28515139e2aa674f8bb54da" +dependencies = [ + "anyhow", + "bigdecimal", + "hex", + "hex-literal", + "num-bigint", + "num-integer", + "num-traits", + "pad", + "prost", + "prost-build", + "prost-types", + "substreams-macro", + "thiserror", +] + +[[package]] +name = "substreams-ethereum" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f45dc04be50b7ca08d6d5c4560ee3eeba16ccaa1c124d0361bb30b5b84e28b" +dependencies = [ + "getrandom", + "num-bigint", + "substreams", + "substreams-ethereum-abigen", + "substreams-ethereum-core", + "substreams-ethereum-derive", +] + +[[package]] +name = "substreams-ethereum-abigen" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c04307913a355aaf2a1bb7186d4bc7e36875f3d4aff77b47e83f1b63b24da55" +dependencies = [ + "anyhow", + "ethabi", + "heck", + "hex", + "prettyplease", + "proc-macro2", + "quote", + "substreams-ethereum-core", + "syn 1.0.109", +] + +[[package]] +name = "substreams-ethereum-core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9048cc9a66873ab7069ef958c2684994e6ee323da49c186b19156fdb4ca131" +dependencies = [ + "bigdecimal", + "ethabi", + "getrandom", + "num-bigint", + "prost", + "prost-build", + "prost-types", + "substreams", +] + +[[package]] +name = "substreams-ethereum-derive" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e862928bee8653f5c9291ac619c8dc0da14ca61d8cd8d89b3acdbbde4d0bf304" +dependencies = [ + "ethabi", + "heck", + "hex", + "num-bigint", + "proc-macro2", + "quote", + "substreams-ethereum-abigen", + "syn 1.0.109", +] + +[[package]] +name = "substreams-macro" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c15595ceab80fece579e462d4823048fe85d67922584c681f5e94305727ad9ee" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tycho-substreams" +version = "0.1.0" +dependencies = [ + "substreams-ethereum", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/crates/tycho-substreams/Cargo.toml b/crates/tycho-substreams/Cargo.toml new file mode 100644 index 0000000..269aea3 --- /dev/null +++ b/crates/tycho-substreams/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "tycho-substreams" +version = "0.1.0" +edition = "2021" + +[dependencies] +substreams-ethereum = "0.9.9" \ No newline at end of file diff --git a/crates/tycho-substreams/Readme.md b/crates/tycho-substreams/Readme.md new file mode 100644 index 0000000..56b374b --- /dev/null +++ b/crates/tycho-substreams/Readme.md @@ -0,0 +1,18 @@ +# Tycho Substreams SDK + +Some shared functionality that is used to create tycho substream packages. + +## Protobuf Models + +Protobuf models are manually synced from the `tycho-indexer` repository whenever they +changed. + +To generate the rust structs run the following command from within the `./proto` +directory: + +```bash +buf generate \ + --path tycho \ + --template ../crates/tycho-substreams/buf.gen.yaml \ + --output ../crates/tycho-substreams/ +``` \ No newline at end of file diff --git a/crates/tycho-substreams/buf.gen.yaml b/crates/tycho-substreams/buf.gen.yaml new file mode 100644 index 0000000..07f4f81 --- /dev/null +++ b/crates/tycho-substreams/buf.gen.yaml @@ -0,0 +1,12 @@ +version: v1 +plugins: + - plugin: buf.build/community/neoeinstein-prost:v0.2.2 + out: src/pb + opt: + - file_descriptor_set=false + - type_attribute=.tycho.evm.v1.Transaction=#[derive(Eq\, Hash)] + + - plugin: buf.build/community/neoeinstein-prost-crate:v0.3.1 + out: src/pb + opt: + - no_features diff --git a/crates/tycho-substreams/src/contract.rs b/crates/tycho-substreams/src/contract.rs new file mode 100644 index 0000000..a0391b3 --- /dev/null +++ b/crates/tycho-substreams/src/contract.rs @@ -0,0 +1,199 @@ +/// This file contains helpers to capture contract changes from the expanded block model. These +/// leverage the `code_changes`, `balance_changes`, and `storage_changes` fields available on the +/// `Call` type provided by block model in a substream (i.e. `logs_and_calls`, etc). +/// +/// ⚠️ These helpers *only* work if the **expanded block model** is available, +/// more [here](https://streamingfastio.medium.com/new-block-model-to-accelerate-chain-integration-9f65126e5425) +use std::collections::HashMap; + +use substreams_ethereum::pb::eth; + +use crate::pb::tycho::evm::v1::{self as tycho}; + +struct SlotValue { + new_value: Vec, + start_value: Vec, +} + +impl SlotValue { + fn has_changed(&self) -> bool { + self.start_value != self.new_value + } +} + +// Uses a map for slots, protobuf does not allow bytes in hashmap keys +pub struct InterimContractChange { + address: Vec, + balance: Vec, + code: Vec, + slots: HashMap, SlotValue>, + change: tycho::ChangeType, +} + +impl From for tycho::ContractChange { + fn from(value: InterimContractChange) -> Self { + tycho::ContractChange { + address: value.address, + balance: value.balance, + code: value.code, + slots: value + .slots + .into_iter() + .filter(|(_, value)| value.has_changed()) + .map(|(slot, value)| tycho::ContractSlot { + slot, + value: value.new_value, + }) + .collect(), + change: value.change.into(), + } + } +} + +pub fn extract_contract_changes bool >( + block: ð::v2::Block, + inclusion_predicate: F, + transaction_contract_changes: &mut HashMap, +) { + let mut changed_contracts: HashMap, InterimContractChange> = HashMap::new(); + + // Collect all accounts created in this block + let created_accounts: HashMap<_, _> = block + .transactions() + .flat_map(|tx| { + tx.calls.iter().flat_map(|call| { + call.account_creations + .iter() + .map(|ac| (&ac.account, ac.ordinal)) + }) + }) + .collect(); + + block.transactions().for_each(|block_tx| { + let mut storage_changes = Vec::new(); + let mut balance_changes = Vec::new(); + let mut code_changes = Vec::new(); + + block_tx + .calls + .iter() + .filter(|call| { + !call.state_reverted + && inclusion_predicate(&call.address) + }) + .for_each(|call| { + storage_changes.extend(call.storage_changes.iter()); + balance_changes.extend(call.balance_changes.iter()); + code_changes.extend(call.code_changes.iter()); + }); + + storage_changes.sort_unstable_by_key(|change| change.ordinal); + balance_changes.sort_unstable_by_key(|change| change.ordinal); + code_changes.sort_unstable_by_key(|change| change.ordinal); + + storage_changes + .iter() + .filter(|changes| { + inclusion_predicate(&changes.address) + }) + .for_each(|storage_change| { + let contract_change = changed_contracts + .entry(storage_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: storage_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&storage_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); + + let slot_value = contract_change + .slots + .entry(storage_change.key.clone()) + .or_insert_with(|| SlotValue { + new_value: storage_change.new_value.clone(), + start_value: storage_change.old_value.clone(), + }); + + slot_value + .new_value + .copy_from_slice(&storage_change.new_value); + }); + + balance_changes + .iter() + .filter(|changes| { + inclusion_predicate(&changes.address) + }) + .for_each(|balance_change| { + let contract_change = changed_contracts + .entry(balance_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: balance_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&balance_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); + + if let Some(new_balance) = &balance_change.new_value { + contract_change.balance.clear(); + contract_change + .balance + .extend_from_slice(&new_balance.bytes); + } + }); + + code_changes + .iter() + .filter(|changes| { + inclusion_predicate(&changes.address) + }) + .for_each(|code_change| { + let contract_change = changed_contracts + .entry(code_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: code_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&code_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); + + contract_change.code.clear(); + contract_change + .code + .extend_from_slice(&code_change.new_code); + }); + + if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() { + transaction_contract_changes + .entry(block_tx.index.into()) + .or_insert_with(|| tycho::TransactionContractChanges { + tx: Some(tycho::Transaction { + hash: block_tx.hash.clone(), + from: block_tx.from.clone(), + to: block_tx.to.clone(), + index: block_tx.index as u64, + }), + contract_changes: vec![], + component_changes: vec![], + balance_changes: vec![], + }) + .contract_changes + .extend(changed_contracts.drain().map(|(_, change)| change.into())); + } + }); +} diff --git a/crates/tycho-substreams/src/lib.rs b/crates/tycho-substreams/src/lib.rs new file mode 100644 index 0000000..2f52c0e --- /dev/null +++ b/crates/tycho-substreams/src/lib.rs @@ -0,0 +1,2 @@ +pub mod contract; +pub mod pb; \ No newline at end of file diff --git a/crates/tycho-substreams/src/pb/mod.rs b/crates/tycho-substreams/src/pb/mod.rs new file mode 100644 index 0000000..43d8838 --- /dev/null +++ b/crates/tycho-substreams/src/pb/mod.rs @@ -0,0 +1,10 @@ +// @generated +pub mod tycho { + pub mod evm { + // @@protoc_insertion_point(attribute:tycho.evm.v1) + pub mod v1 { + include!("tycho.evm.v1.rs"); + // @@protoc_insertion_point(tycho.evm.v1) + } + } +} diff --git a/crates/tycho-substreams/src/pb/tycho.evm.v1.rs b/crates/tycho-substreams/src/pb/tycho.evm.v1.rs new file mode 100644 index 0000000..7424ba2 --- /dev/null +++ b/crates/tycho-substreams/src/pb/tycho.evm.v1.rs @@ -0,0 +1,309 @@ +// @generated +// This file contains the proto definitions for Substreams common to all integrations. + +/// A struct describing a block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Block { + /// The blocks hash. + #[prost(bytes="vec", tag="1")] + pub hash: ::prost::alloc::vec::Vec, + /// The parent blocks hash. + #[prost(bytes="vec", tag="2")] + pub parent_hash: ::prost::alloc::vec::Vec, + /// The block number. + #[prost(uint64, tag="3")] + pub number: u64, + /// The block timestamp. + #[prost(uint64, tag="4")] + pub ts: u64, +} +/// A struct describing a transaction. +#[derive(Eq, Hash)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + /// The transaction hash. + #[prost(bytes="vec", tag="1")] + pub hash: ::prost::alloc::vec::Vec, + /// The sender of the transaction. + #[prost(bytes="vec", tag="2")] + pub from: ::prost::alloc::vec::Vec, + /// The receiver of the transaction. + #[prost(bytes="vec", tag="3")] + pub to: ::prost::alloc::vec::Vec, + /// The transactions index within the block. + /// TODO: should this be uint32? to match the type from the native substream type? + #[prost(uint64, tag="4")] + pub index: u64, +} +/// A custom struct representing an arbitrary attribute of a protocol component. +/// This is mainly used by the native integration to track the necessary information about the protocol. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Attribute { + /// The name of the attribute. + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + /// The value of the attribute. + #[prost(bytes="vec", tag="2")] + pub value: ::prost::alloc::vec::Vec, + /// The type of change the attribute underwent. + #[prost(enumeration="ChangeType", tag="3")] + pub change: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProtocolType { + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + #[prost(enumeration="FinancialType", tag="2")] + pub financial_type: i32, + #[prost(message, repeated, tag="3")] + pub attribute_schema: ::prost::alloc::vec::Vec, + #[prost(enumeration="ImplementationType", tag="4")] + pub implementation_type: i32, +} +/// A struct describing a part of the protocol. +/// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, +/// the component would represent a single contract. In case of VM integration, such component would +/// not need any attributes, because all the relevant info would be tracked via storage slots and balance changes. +/// It can also be a wrapping contract, like WETH, that has a constant price, but it allows swapping tokens. +/// This is why the name ProtocolComponent is used instead of "Pool" or "Pair". +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProtocolComponent { + /// A unique identifier for the component within the protocol. + /// Can be e.g. a stringified address or a string describing the trading pair. + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + /// Addresses of the ERC20 tokens used by the component. + #[prost(bytes="vec", repeated, tag="2")] + pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Addresses of the contracts used by the component. + /// Usually it is a single contract, but some protocols use multiple contracts. + #[prost(bytes="vec", repeated, tag="3")] + pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Attributes of the component. Used mainly be the native integration. + /// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. + #[prost(message, repeated, tag="4")] + pub static_att: ::prost::alloc::vec::Vec, + /// Type of change the component underwent. + #[prost(enumeration="ChangeType", tag="5")] + pub change: i32, + /// / Represents the functionality of the component. + #[prost(message, optional, tag="6")] + pub protocol_type: ::core::option::Option, + /// Transaction where this component was created + #[prost(message, optional, tag="7")] + pub tx: ::core::option::Option, +} +/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. +/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. +/// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceChange { + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="1")] + pub token: ::prost::alloc::vec::Vec, + /// The new balance of the token. + #[prost(bytes="vec", tag="2")] + pub balance: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. + /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="3")] + pub component_id: ::prost::alloc::vec::Vec, +} +/// Enum to specify the type of a change. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ChangeType { + Unspecified = 0, + Update = 1, + Creation = 2, + Deletion = 3, +} +impl ChangeType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED", + ChangeType::Update => "CHANGE_TYPE_UPDATE", + ChangeType::Creation => "CHANGE_TYPE_CREATION", + ChangeType::Deletion => "CHANGE_TYPE_DELETION", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified), + "CHANGE_TYPE_UPDATE" => Some(Self::Update), + "CHANGE_TYPE_CREATION" => Some(Self::Creation), + "CHANGE_TYPE_DELETION" => Some(Self::Deletion), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FinancialType { + Swap = 0, + Lend = 1, + Leverage = 2, + Psm = 3, +} +impl FinancialType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FinancialType::Swap => "SWAP", + FinancialType::Lend => "LEND", + FinancialType::Leverage => "LEVERAGE", + FinancialType::Psm => "PSM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SWAP" => Some(Self::Swap), + "LEND" => Some(Self::Lend), + "LEVERAGE" => Some(Self::Leverage), + "PSM" => Some(Self::Psm), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ImplementationType { + Vm = 0, + Custom = 1, +} +impl ImplementationType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ImplementationType::Vm => "VM", + ImplementationType::Custom => "CUSTOM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VM" => Some(Self::Vm), + "CUSTOM" => Some(Self::Custom), + _ => None, + } + } +} +// This file contains the definition for the native integration of Substreams. + +/// A component is a set of attributes that are associated with a custom entity. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EntityChanges { + /// A unique identifier of the entity within the protocol. + #[prost(string, tag="1")] + pub component_id: ::prost::alloc::string::String, + /// The set of attributes that are associated with the entity. + #[prost(message, repeated, tag="2")] + pub attributes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEntityChanges { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub entity_changes: ::prost::alloc::vec::Vec, + /// An array of newly added components. + #[prost(message, repeated, tag="3")] + pub component_changes: ::prost::alloc::vec::Vec, + /// An array of balance changes to components. + #[prost(message, repeated, tag="4")] + pub balance_changes: ::prost::alloc::vec::Vec, +} +/// A set of transaction changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockEntityChanges { + /// The block for which these changes are collectively computed. + #[prost(message, optional, tag="1")] + pub block: ::core::option::Option, + /// The set of transaction changes observed in the specified block. + #[prost(message, repeated, tag="2")] + pub changes: ::prost::alloc::vec::Vec, +} +// This file contains proto definitions specific to the VM integration. + +/// A key value entry into contract storage. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ContractSlot { + /// A contract's storage slot. + #[prost(bytes="vec", tag="2")] + pub slot: ::prost::alloc::vec::Vec, + /// The new value for this storage slot. + #[prost(bytes="vec", tag="3")] + pub value: ::prost::alloc::vec::Vec, +} +/// Changes made to a single contract's state. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ContractChange { + /// The contract's address + #[prost(bytes="vec", tag="1")] + pub address: ::prost::alloc::vec::Vec, + /// The new native balance of the contract, empty bytes indicates no change. + #[prost(bytes="vec", tag="2")] + pub balance: ::prost::alloc::vec::Vec, + /// The new code of the contract, empty bytes indicates no change. + #[prost(bytes="vec", tag="3")] + pub code: ::prost::alloc::vec::Vec, + /// The changes to this contract's slots, empty sequence indicates no change. + #[prost(message, repeated, tag="4")] + pub slots: ::prost::alloc::vec::Vec, + /// Whether this is an update, a creation or a deletion. + #[prost(enumeration="ChangeType", tag="5")] + pub change: i32, +} +/// A set of changes aggregated by transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionContractChanges { + /// The transaction instance that results in the changes. + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + /// Contains the changes induced by the above transaction, aggregated on a per-contract basis. + /// Must include changes to every contract that is tracked by all ProtocolComponents. + #[prost(message, repeated, tag="2")] + pub contract_changes: ::prost::alloc::vec::Vec, + /// An array of any component changes. + #[prost(message, repeated, tag="3")] + pub component_changes: ::prost::alloc::vec::Vec, + /// An array of balance changes to components. + #[prost(message, repeated, tag="4")] + pub balance_changes: ::prost::alloc::vec::Vec, +} +/// A set of transaction changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockContractChanges { + /// The block for which these changes are collectively computed. + #[prost(message, optional, tag="1")] + pub block: ::core::option::Option, + /// The set of transaction changes observed in the specified block. + #[prost(message, repeated, tag="2")] + pub changes: ::prost::alloc::vec::Vec, +} +// @@protoc_insertion_point(module) From 3d248f3fa1e18a95efae60237e789d5a6ae6fba8 Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 18:46:10 +0000 Subject: [PATCH 15/37] Implement helpers for relative balances. Adds some helpers that will users help to convert relative balances changes to absolute ones. The goal is to make this as reduce the effort of the user to implementing a simple map handler that extracts relative balances changes. --- crates/tycho-substreams/Cargo.lock | 17 +- crates/tycho-substreams/Cargo.toml | 6 +- crates/tycho-substreams/rustfmt.toml | 13 + crates/tycho-substreams/src/balances.rs | 306 ++++++++++++++++++ crates/tycho-substreams/src/contract.rs | 245 +++++++------- crates/tycho-substreams/src/lib.rs | 6 +- crates/tycho-substreams/src/mock_store.rs | 93 ++++++ .../tycho-substreams/src/pb/tycho.evm.v1.rs | 51 ++- crates/tycho-substreams/src/utils.rs | 24 ++ 9 files changed, 632 insertions(+), 129 deletions(-) create mode 100644 crates/tycho-substreams/rustfmt.toml create mode 100644 crates/tycho-substreams/src/balances.rs create mode 100644 crates/tycho-substreams/src/mock_store.rs create mode 100644 crates/tycho-substreams/src/utils.rs diff --git a/crates/tycho-substreams/Cargo.lock b/crates/tycho-substreams/Cargo.lock index 5e61c4a..cd827d8 100644 --- a/crates/tycho-substreams/Cargo.lock +++ b/crates/tycho-substreams/Cargo.lock @@ -333,6 +333,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -530,7 +539,7 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "multimap", @@ -551,7 +560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", @@ -908,6 +917,10 @@ dependencies = [ name = "tycho-substreams" version = "0.1.0" dependencies = [ + "hex", + "itertools 0.12.1", + "prost", + "substreams", "substreams-ethereum", ] diff --git a/crates/tycho-substreams/Cargo.toml b/crates/tycho-substreams/Cargo.toml index 269aea3..cc0f7bc 100644 --- a/crates/tycho-substreams/Cargo.toml +++ b/crates/tycho-substreams/Cargo.toml @@ -4,4 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -substreams-ethereum = "0.9.9" \ No newline at end of file +substreams-ethereum = "0.9.9" +substreams = "0.5" +prost = "0.11" +hex = "0.4.3" +itertools = "0.12.0" \ No newline at end of file diff --git a/crates/tycho-substreams/rustfmt.toml b/crates/tycho-substreams/rustfmt.toml new file mode 100644 index 0000000..d0c0193 --- /dev/null +++ b/crates/tycho-substreams/rustfmt.toml @@ -0,0 +1,13 @@ +reorder_imports = true +imports_granularity = "Crate" +use_small_heuristics = "Max" +comment_width = 100 +wrap_comments = true +binop_separator = "Back" +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true +chain_width = 40 +ignore = [ + "src/pb", +] \ No newline at end of file diff --git a/crates/tycho-substreams/src/balances.rs b/crates/tycho-substreams/src/balances.rs new file mode 100644 index 0000000..dbc780a --- /dev/null +++ b/crates/tycho-substreams/src/balances.rs @@ -0,0 +1,306 @@ +//! Utilities to handle relative balances. +//! +//! +//! To aggregate relative balances changes to absolute balances the general approach is: +//! +//! 1. Use a map function that will extract a `BlockBalanceDeltas` message. BalanceDeltas +//! within this message are required to have increasing ordinals so that +//! the order of relative balance changes is unambiguous. +//! 2. Store the balances changes with a store handler. You can use the +//! `store_balance_changes` library method directly for this. +//! 3. In the output module, use aggregate_balance_changes to receive an +//! aggregated map of absolute balances. +//! +use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas}; +use itertools::Itertools; +use std::collections::HashMap; +use std::str::FromStr; +use substreams::key; +use substreams::pb::substreams::StoreDeltas; +use substreams::prelude::{BigInt, StoreAdd}; + +pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd) { + let mut previous_ordinal = HashMap::::new(); + deltas + .balance_deltas + .iter() + .for_each(|delta| { + let balance_key = format!( + "{0}:{1}", + String::from_utf8(delta.component_id.clone()) + .expect("delta.component_id is not valid utf-8!"), + hex::encode(&delta.token) + ); + let current_ord = delta.ord; + previous_ordinal + .entry(balance_key.clone()) + .and_modify(|ord| { + // ordinals must arrive in increasing order + if *ord >= current_ord { + panic!( + "Invalid ordinal sequence for {}: {} >= {}", + balance_key, *ord, current_ord + ); + } + *ord = current_ord; + }) + .or_insert(delta.ord); + store.add(delta.ord, balance_key, BigInt::from_signed_bytes_be(&delta.delta)); + }); +} + +pub fn aggregate_balances_changes( + balance_store: StoreDeltas, + deltas: BlockBalanceDeltas, +) -> HashMap, HashMap, BalanceChange>> { + balance_store + .deltas + .into_iter() + .zip(deltas.balance_deltas) + .map(|(store_delta, balance_delta)| { + let component_id = key::segment_at(&store_delta.key, 0); + let token_id = key::segment_at(&store_delta.key, 1); + // store_delta.new_value is an ASCII string representing an integer + let ascii_string = + String::from_utf8(store_delta.new_value.clone()).expect("Invalid UTF-8 sequence"); + let balance = BigInt::from_str(&ascii_string).expect("Failed to parse integer"); + let big_endian_bytes_balance = balance.to_bytes_be().1; + + ( + balance_delta.tx.unwrap(), + BalanceChange { + token: hex::decode(token_id).expect("Token ID not valid hex"), + balance: big_endian_bytes_balance, + component_id: component_id.as_bytes().to_vec(), + }, + ) + }) + // We need to group the balance changes by tx hash for the `TransactionContractChanges` agg + .group_by(|(tx, _)| tx.hash.clone()) + .into_iter() + .map(|(txh, group)| { + let balances = group + .into_iter() + .map(|(_, delta)| (delta.token.clone(), delta)) + .collect(); + (txh, balances) + }) + .collect() +} + +mod tests { + use super::*; + use crate::mock_store::MockStore; + use crate::pb::tycho::evm::v1::{BalanceDelta, Transaction}; + use substreams::pb::substreams::StoreDelta; + use substreams::prelude::{StoreGet, StoreNew}; + + fn block_balance_deltas() -> BlockBalanceDeltas { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + BlockBalanceDeltas { + balance_deltas: vec![ + BalanceDelta { + ord: 0, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_0.clone(), + delta: BigInt::from_str("+1000") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 2, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_1.clone(), + delta: BigInt::from_str("+100") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 3, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_1.clone(), + delta: BigInt::from_str("50") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 10, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_0.clone(), + delta: BigInt::from_str("-1") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + ], + } + } + fn store_deltas() -> StoreDeltas { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + + let t0_key = + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(&token_0)); + let t1_key = + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(&token_1)); + StoreDeltas { + deltas: vec![ + StoreDelta { + operation: 0, + ordinal: 0, + key: t0_key.clone(), + old_value: BigInt::from(0) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(1000) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 2, + key: t1_key.clone(), + old_value: BigInt::from(0) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(100) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 3, + key: t1_key.clone(), + old_value: BigInt::from(100) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(150) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 10, + key: t0_key.clone(), + old_value: BigInt::from(1000) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(999) + .to_string() + .as_bytes() + .to_vec(), + }, + ], + } + } + + #[test] + fn test_store_balances() { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + let deltas = block_balance_deltas(); + let store = ::new(); + + store_balance_changes(deltas, store.clone()); + let res_0 = store.get_last(format!( + "{}:{}", + String::from_utf8(comp_id.clone()).unwrap(), + hex::encode(&token_0) + )); + let res_1 = store.get_last(format!( + "{}:{}", + String::from_utf8(comp_id.clone()).unwrap(), + hex::encode(&token_1) + )); + + assert_eq!(res_0, Some(BigInt::from_str("+999").unwrap())); + assert_eq!(res_1, Some(BigInt::from_str("+150").unwrap())); + } + + #[test] + fn test_aggregate_balances_changes() { + let store_deltas = store_deltas(); + let balance_deltas = block_balance_deltas(); + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + let exp = [( + vec![0, 1], + [ + ( + token_0.clone(), + BalanceChange { + token: token_0, + balance: BigInt::from(999) + .to_signed_bytes_be() + .to_vec(), + component_id: comp_id.clone(), + }, + ), + ( + token_1.clone(), + BalanceChange { + token: token_1, + balance: vec![150], + component_id: comp_id.clone(), + }, + ), + ] + .into_iter() + .collect(), + )] + .into_iter() + .collect(); + + let res = aggregate_balances_changes(store_deltas, balance_deltas); + dbg!(&res); + + assert_eq!(res, exp); + } +} diff --git a/crates/tycho-substreams/src/contract.rs b/crates/tycho-substreams/src/contract.rs index a0391b3..79ad454 100644 --- a/crates/tycho-substreams/src/contract.rs +++ b/crates/tycho-substreams/src/contract.rs @@ -22,7 +22,7 @@ impl SlotValue { } // Uses a map for slots, protobuf does not allow bytes in hashmap keys -pub struct InterimContractChange { +struct InterimContractChange { address: Vec, balance: Vec, code: Vec, @@ -40,17 +40,14 @@ impl From for tycho::ContractChange { .slots .into_iter() .filter(|(_, value)| value.has_changed()) - .map(|(slot, value)| tycho::ContractSlot { - slot, - value: value.new_value, - }) + .map(|(slot, value)| tycho::ContractSlot { slot, value: value.new_value }) .collect(), change: value.change.into(), } } } -pub fn extract_contract_changes bool >( +pub fn extract_contract_changes bool>( block: ð::v2::Block, inclusion_predicate: F, transaction_contract_changes: &mut HashMap, @@ -69,131 +66,131 @@ pub fn extract_contract_changes bool >( }) .collect(); - block.transactions().for_each(|block_tx| { - let mut storage_changes = Vec::new(); - let mut balance_changes = Vec::new(); - let mut code_changes = Vec::new(); + block + .transactions() + .for_each(|block_tx| { + let mut storage_changes = Vec::new(); + let mut balance_changes = Vec::new(); + let mut code_changes = Vec::new(); - block_tx - .calls - .iter() - .filter(|call| { - !call.state_reverted - && inclusion_predicate(&call.address) - }) - .for_each(|call| { - storage_changes.extend(call.storage_changes.iter()); - balance_changes.extend(call.balance_changes.iter()); - code_changes.extend(call.code_changes.iter()); - }); + block_tx + .calls + .iter() + .filter(|call| !call.state_reverted && inclusion_predicate(&call.address)) + .for_each(|call| { + storage_changes.extend(call.storage_changes.iter()); + balance_changes.extend(call.balance_changes.iter()); + code_changes.extend(call.code_changes.iter()); + }); - storage_changes.sort_unstable_by_key(|change| change.ordinal); - balance_changes.sort_unstable_by_key(|change| change.ordinal); - code_changes.sort_unstable_by_key(|change| change.ordinal); + storage_changes.sort_unstable_by_key(|change| change.ordinal); + balance_changes.sort_unstable_by_key(|change| change.ordinal); + code_changes.sort_unstable_by_key(|change| change.ordinal); - storage_changes - .iter() - .filter(|changes| { - inclusion_predicate(&changes.address) - }) - .for_each(|storage_change| { - let contract_change = changed_contracts - .entry(storage_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: storage_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&storage_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); + storage_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|storage_change| { + let contract_change = changed_contracts + .entry(storage_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: storage_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&storage_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); - let slot_value = contract_change - .slots - .entry(storage_change.key.clone()) - .or_insert_with(|| SlotValue { - new_value: storage_change.new_value.clone(), - start_value: storage_change.old_value.clone(), - }); + let slot_value = contract_change + .slots + .entry(storage_change.key.clone()) + .or_insert_with(|| SlotValue { + new_value: storage_change.new_value.clone(), + start_value: storage_change.old_value.clone(), + }); - slot_value - .new_value - .copy_from_slice(&storage_change.new_value); - }); + slot_value + .new_value + .copy_from_slice(&storage_change.new_value); + }); - balance_changes - .iter() - .filter(|changes| { - inclusion_predicate(&changes.address) - }) - .for_each(|balance_change| { - let contract_change = changed_contracts - .entry(balance_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: balance_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&balance_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); + balance_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|balance_change| { + let contract_change = changed_contracts + .entry(balance_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: balance_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&balance_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); - if let Some(new_balance) = &balance_change.new_value { - contract_change.balance.clear(); + if let Some(new_balance) = &balance_change.new_value { + contract_change.balance.clear(); + contract_change + .balance + .extend_from_slice(&new_balance.bytes); + } + }); + + code_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|code_change| { + let contract_change = changed_contracts + .entry(code_change.address.clone()) + .or_insert_with(|| InterimContractChange { + address: code_change.address.clone(), + balance: Vec::new(), + code: Vec::new(), + slots: HashMap::new(), + change: if created_accounts.contains_key(&code_change.address) { + tycho::ChangeType::Creation + } else { + tycho::ChangeType::Update + }, + }); + + contract_change.code.clear(); contract_change - .balance - .extend_from_slice(&new_balance.bytes); - } - }); + .code + .extend_from_slice(&code_change.new_code); + }); - code_changes - .iter() - .filter(|changes| { - inclusion_predicate(&changes.address) - }) - .for_each(|code_change| { - let contract_change = changed_contracts - .entry(code_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: code_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&code_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); - - contract_change.code.clear(); - contract_change - .code - .extend_from_slice(&code_change.new_code); - }); - - if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() { - transaction_contract_changes - .entry(block_tx.index.into()) - .or_insert_with(|| tycho::TransactionContractChanges { - tx: Some(tycho::Transaction { - hash: block_tx.hash.clone(), - from: block_tx.from.clone(), - to: block_tx.to.clone(), - index: block_tx.index as u64, - }), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - }) - .contract_changes - .extend(changed_contracts.drain().map(|(_, change)| change.into())); - } - }); + if !storage_changes.is_empty() + || !balance_changes.is_empty() + || !code_changes.is_empty() + { + transaction_contract_changes + .entry(block_tx.index.into()) + .or_insert_with(|| tycho::TransactionContractChanges { + tx: Some(tycho::Transaction { + hash: block_tx.hash.clone(), + from: block_tx.from.clone(), + to: block_tx.to.clone(), + index: block_tx.index as u64, + }), + contract_changes: vec![], + component_changes: vec![], + balance_changes: vec![], + }) + .contract_changes + .extend( + changed_contracts + .drain() + .map(|(_, change)| change.into()), + ); + } + }); } diff --git a/crates/tycho-substreams/src/lib.rs b/crates/tycho-substreams/src/lib.rs index 2f52c0e..d5b0d0f 100644 --- a/crates/tycho-substreams/src/lib.rs +++ b/crates/tycho-substreams/src/lib.rs @@ -1,2 +1,6 @@ +pub mod balances; pub mod contract; -pub mod pb; \ No newline at end of file +mod mock_store; +pub mod pb; +// TODO: consider removing this module, after integrating with balancer +pub mod utils; diff --git a/crates/tycho-substreams/src/mock_store.rs b/crates/tycho-substreams/src/mock_store.rs new file mode 100644 index 0000000..a1c0cd2 --- /dev/null +++ b/crates/tycho-substreams/src/mock_store.rs @@ -0,0 +1,93 @@ +//! Contains a mock store for internal testing. +//! +//! Might make this public alter to users can test their store handlers. +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; +use substreams::prelude::{BigInt, StoreDelete, StoreGet, StoreNew}; +use substreams::store::StoreAdd; + +#[derive(Debug, Clone)] +pub struct MockStore { + data: Rc>>>, +} + +impl StoreDelete for MockStore { + fn delete_prefix(&self, _ord: i64, prefix: &String) { + self.data + .borrow_mut() + .retain(|k, _| !k.starts_with(prefix)); + } +} + +impl StoreNew for MockStore { + fn new() -> Self { + Self { data: Rc::new(RefCell::new(HashMap::new())) } + } +} + +impl StoreAdd for MockStore { + fn add>(&self, ord: u64, key: K, value: BigInt) { + let mut guard = self.data.borrow_mut(); + guard + .entry(key.as_ref().to_string()) + .and_modify(|v| { + let prev_value = v.last().unwrap().1.clone(); + v.push((ord, prev_value + value.clone())); + }) + .or_insert(vec![(ord, value)]); + } + + fn add_many>(&self, _ord: u64, _keys: &Vec, _value: BigInt) { + todo!() + } +} + +impl StoreGet for MockStore { + fn new(_idx: u32) -> Self { + Self { data: Rc::new(RefCell::new(HashMap::new())) } + } + + fn get_at>(&self, ord: u64, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| { + v.iter() + .find(|(current_ord, _)| *current_ord == ord) + .unwrap() + .1 + .clone() + }) + } + + fn get_last>(&self, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.last().unwrap().1.clone()) + } + + fn get_first>(&self, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.first().unwrap().1.clone()) + } + + fn has_at>(&self, ord: u64, key: K) -> bool { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.iter().any(|(v, _)| *v == ord)) + .unwrap_or(false) + } + + fn has_last>(&self, _key: K) -> bool { + todo!() + } + + fn has_first>(&self, _key: K) -> bool { + todo!() + } +} diff --git a/crates/tycho-substreams/src/pb/tycho.evm.v1.rs b/crates/tycho-substreams/src/pb/tycho.evm.v1.rs index 7424ba2..5409eff 100644 --- a/crates/tycho-substreams/src/pb/tycho.evm.v1.rs +++ b/crates/tycho-substreams/src/pb/tycho.evm.v1.rs @@ -107,7 +107,7 @@ pub struct BalanceChange { /// The address of the ERC20 token whose balance changed. #[prost(bytes="vec", tag="1")] pub token: ::prost::alloc::vec::Vec, - /// The new balance of the token. + /// The new balance of the token. Note: it must be a big endian encoded int. #[prost(bytes="vec", tag="2")] pub balance: ::prost::alloc::vec::Vec, /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. @@ -244,6 +244,55 @@ pub struct BlockEntityChanges { #[prost(message, repeated, tag="2")] pub changes: ::prost::alloc::vec::Vec, } +/// A message containing relative balance changes. +/// +/// Used to track token balances of protocol components in case they are only +/// available as relative values within a block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDelta { + /// The ordinal of the balance change. Must be unique & deterministic over all balances + /// changes within a block. + #[prost(uint64, tag="1")] + pub ord: u64, + /// The tx hash of the transaction that caused the balance change. + #[prost(message, optional, tag="2")] + pub tx: ::core::option::Option, + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="3")] + pub token: ::prost::alloc::vec::Vec, + /// The delta balance of the token. + #[prost(bytes="vec", tag="4")] + pub delta: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. + /// If the protocol component includes multiple contracts, the balance change must be + /// aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="5")] + pub component_id: ::prost::alloc::vec::Vec, +} +/// A set of balances deltas, usually a group of changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockBalanceDeltas { + #[prost(message, repeated, tag="1")] + pub balance_deltas: ::prost::alloc::vec::Vec, +} +/// A message containing protocol components that were created by a single tx. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionProtocolComponents { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub components: ::prost::alloc::vec::Vec, +} +/// All protocol components that were created within a block with their corresponding tx. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockTransactionProtocolComponents { + #[prost(message, repeated, tag="1")] + pub tx_components: ::prost::alloc::vec::Vec, +} // This file contains proto definitions specific to the VM integration. /// A key value entry into contract storage. diff --git a/crates/tycho-substreams/src/utils.rs b/crates/tycho-substreams/src/utils.rs new file mode 100644 index 0000000..e4729db --- /dev/null +++ b/crates/tycho-substreams/src/utils.rs @@ -0,0 +1,24 @@ +use crate::pb::tycho::evm::v1::Transaction; + +/// This struct purely exists to spoof the `PartialEq` trait for `Transaction` so we can use it in +/// a later groupby operation. +#[derive(Debug)] +pub struct TransactionWrapper(Transaction); + +impl TransactionWrapper { + pub fn new(tx: Transaction) -> Self { + Self(tx) + } +} + +impl PartialEq for TransactionWrapper { + fn eq(&self, other: &Self) -> bool { + self.0.hash == other.0.hash + } +} + +impl From for Transaction { + fn from(value: TransactionWrapper) -> Self { + value.0 + } +} From d9fe9b1e1cad391413d2a14bb144554dbb4ab633 Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 21:06:55 +0000 Subject: [PATCH 16/37] Integrate balancer substream with sdk. We defer the contract storage extraction as well as the balance handling (apart from actually extracing relative deltas) to the SDK. --- crates/tycho-substreams/src/balances.rs | 65 ++-- crates/tycho-substreams/src/pb/mod.rs | 11 + substreams/ethereum-balancer/Cargo.lock | 12 + substreams/ethereum-balancer/Cargo.toml | 1 + .../ethereum-balancer/src/contract_changes.rs | 211 ------------ substreams/ethereum-balancer/src/lib.rs | 2 - substreams/ethereum-balancer/src/modules.rs | 115 +++---- substreams/ethereum-balancer/src/pb/mod.rs | 10 - .../ethereum-balancer/src/pb/tycho.evm.v1.rs | 319 ------------------ .../ethereum-balancer/src/pool_factories.rs | 6 +- 10 files changed, 102 insertions(+), 650 deletions(-) delete mode 100644 substreams/ethereum-balancer/src/contract_changes.rs delete mode 100644 substreams/ethereum-balancer/src/pb/mod.rs delete mode 100644 substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs diff --git a/crates/tycho-substreams/src/balances.rs b/crates/tycho-substreams/src/balances.rs index dbc780a..2547723 100644 --- a/crates/tycho-substreams/src/balances.rs +++ b/crates/tycho-substreams/src/balances.rs @@ -11,7 +11,7 @@ //! 3. In the output module, use aggregate_balance_changes to receive an //! aggregated map of absolute balances. //! -use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas}; +use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}; use itertools::Itertools; use std::collections::HashMap; use std::str::FromStr; @@ -52,7 +52,7 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd HashMap, HashMap, BalanceChange>> { +) -> HashMap, (Transaction, HashMap, BalanceChange>)> { balance_store .deltas .into_iter() @@ -79,15 +79,18 @@ pub fn aggregate_balances_changes( .group_by(|(tx, _)| tx.hash.clone()) .into_iter() .map(|(txh, group)| { - let balances = group + let (mut transactions, balance_changes): (Vec<_>, Vec<_>) = group.into_iter().unzip(); + + let balances = balance_changes .into_iter() - .map(|(_, delta)| (delta.token.clone(), delta)) + .map(|balance_change| (balance_change.token.clone(), balance_change)) .collect(); - (txh, balances) + (txh, (transactions.pop().unwrap(), balances)) }) .collect() } +#[cfg(test)] mod tests { use super::*; use crate::mock_store::MockStore; @@ -270,37 +273,39 @@ mod tests { .to_vec(); let token_0 = hex::decode("bad999").unwrap(); let token_1 = hex::decode("babe00").unwrap(); + let exp = [( vec![0, 1], - [ - ( - token_0.clone(), - BalanceChange { - token: token_0, - balance: BigInt::from(999) - .to_signed_bytes_be() - .to_vec(), - component_id: comp_id.clone(), - }, - ), - ( - token_1.clone(), - BalanceChange { - token: token_1, - balance: vec![150], - component_id: comp_id.clone(), - }, - ), - ] - .into_iter() - .collect(), + ( + Transaction { hash: vec![0, 1], from: vec![9, 9], to: vec![8, 8], index: 0 }, + [ + ( + token_0.clone(), + BalanceChange { + token: token_0, + balance: BigInt::from(999) + .to_signed_bytes_be() + .to_vec(), + component_id: comp_id.clone(), + }, + ), + ( + token_1.clone(), + BalanceChange { + token: token_1, + balance: vec![150], + component_id: comp_id.clone(), + }, + ), + ] + .into_iter() + .collect::>(), + ), )] .into_iter() - .collect(); + .collect::>(); let res = aggregate_balances_changes(store_deltas, balance_deltas); - dbg!(&res); - assert_eq!(res, exp); } } diff --git a/crates/tycho-substreams/src/pb/mod.rs b/crates/tycho-substreams/src/pb/mod.rs index 43d8838..f5cd0b0 100644 --- a/crates/tycho-substreams/src/pb/mod.rs +++ b/crates/tycho-substreams/src/pb/mod.rs @@ -5,6 +5,17 @@ pub mod tycho { pub mod v1 { include!("tycho.evm.v1.rs"); // @@protoc_insertion_point(tycho.evm.v1) + + impl TransactionContractChanges { + pub fn new(tx: &Transaction) -> Self { + Self { + tx: Some(tx.clone()), + contract_changes: vec![], + component_changes: vec![], + balance_changes: vec![], + } + } + } } } } diff --git a/substreams/ethereum-balancer/Cargo.lock b/substreams/ethereum-balancer/Cargo.lock index b05dce5..e2d81a0 100644 --- a/substreams/ethereum-balancer/Cargo.lock +++ b/substreams/ethereum-balancer/Cargo.lock @@ -931,6 +931,7 @@ dependencies = [ "prost-types 0.12.3", "substreams", "substreams-ethereum", + "tycho-substreams", ] [[package]] @@ -1064,6 +1065,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "tycho-substreams" +version = "0.1.0" +dependencies = [ + "hex", + "itertools 0.12.0", + "prost 0.11.9", + "substreams", + "substreams-ethereum", +] + [[package]] name = "typenum" version = "1.17.0" diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml index ace53d3..0a964e5 100644 --- a/substreams/ethereum-balancer/Cargo.toml +++ b/substreams/ethereum-balancer/Cargo.toml @@ -19,6 +19,7 @@ anyhow = "1.0.75" prost-types = "0.12.3" num-bigint = "0.4.4" itertools = "0.12.0" +tycho-substreams = {path ="../../crates/tycho-substreams"} [build-dependencies] anyhow = "1" diff --git a/substreams/ethereum-balancer/src/contract_changes.rs b/substreams/ethereum-balancer/src/contract_changes.rs deleted file mode 100644 index 664b0e7..0000000 --- a/substreams/ethereum-balancer/src/contract_changes.rs +++ /dev/null @@ -1,211 +0,0 @@ -/// This file contains helpers to capture contract changes from the expanded block model. These -/// leverage the `code_changes`, `balance_changes`, and `storage_changes` fields available on the -/// `Call` type provided by block model in a substream (i.e. `logs_and_calls`, etc). -/// -/// ⚠️ These helpers *only* work if the **expanded block model** is available, more info blow. -/// https://streamingfastio.medium.com/new-block-model-to-accelerate-chain-integration-9f65126e5425 -use std::collections::HashMap; - -use substreams_ethereum::pb::eth; - -use pb::tycho::evm::v1::{self as tycho}; - -use substreams::store::{StoreGet, StoreGetInt64}; - -use crate::pb; - -struct SlotValue { - new_value: Vec, - start_value: Vec, -} - -impl SlotValue { - fn has_changed(&self) -> bool { - self.start_value != self.new_value - } -} - -// Uses a map for slots, protobuf does not allow bytes in hashmap keys -pub struct InterimContractChange { - address: Vec, - balance: Vec, - code: Vec, - slots: HashMap, SlotValue>, - change: tycho::ChangeType, -} - -impl From for tycho::ContractChange { - fn from(value: InterimContractChange) -> Self { - tycho::ContractChange { - address: value.address, - balance: value.balance, - code: value.code, - slots: value - .slots - .into_iter() - .filter(|(_, value)| value.has_changed()) - .map(|(slot, value)| tycho::ContractSlot { - slot, - value: value.new_value, - }) - .collect(), - change: value.change.into(), - } - } -} - -pub fn extract_contract_changes( - block: ð::v2::Block, - contracts: StoreGetInt64, - transaction_contract_changes: &mut HashMap, -) { - let mut changed_contracts: HashMap, InterimContractChange> = HashMap::new(); - - // Collect all accounts created in this block - let created_accounts: HashMap<_, _> = block - .transactions() - .flat_map(|tx| { - tx.calls.iter().flat_map(|call| { - call.account_creations - .iter() - .map(|ac| (&ac.account, ac.ordinal)) - }) - }) - .collect(); - - block.transactions().for_each(|block_tx| { - let mut storage_changes = Vec::new(); - let mut balance_changes = Vec::new(); - let mut code_changes = Vec::new(); - - block_tx - .calls - .iter() - .filter(|call| { - !call.state_reverted - && contracts - .get_last(format!("pool:{0}", hex::encode(&call.address))) - .is_some() - }) - .for_each(|call| { - storage_changes.extend(call.storage_changes.iter()); - balance_changes.extend(call.balance_changes.iter()); - code_changes.extend(call.code_changes.iter()); - }); - - storage_changes.sort_unstable_by_key(|change| change.ordinal); - balance_changes.sort_unstable_by_key(|change| change.ordinal); - code_changes.sort_unstable_by_key(|change| change.ordinal); - - storage_changes - .iter() - .filter(|changes| { - contracts - .get_last(format!("pool:{0}", hex::encode(&changes.address))) - .is_some() - }) - .for_each(|storage_change| { - let contract_change = changed_contracts - .entry(storage_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: storage_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&storage_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); - - let slot_value = contract_change - .slots - .entry(storage_change.key.clone()) - .or_insert_with(|| SlotValue { - new_value: storage_change.new_value.clone(), - start_value: storage_change.old_value.clone(), - }); - - slot_value - .new_value - .copy_from_slice(&storage_change.new_value); - }); - - balance_changes - .iter() - .filter(|changes| { - contracts - .get_last(format!("pool:{0}", hex::encode(&changes.address))) - .is_some() - }) - .for_each(|balance_change| { - let contract_change = changed_contracts - .entry(balance_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: balance_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&balance_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); - - if let Some(new_balance) = &balance_change.new_value { - contract_change.balance.clear(); - contract_change - .balance - .extend_from_slice(&new_balance.bytes); - } - }); - - code_changes - .iter() - .filter(|changes| { - contracts - .get_last(format!("pool:{0}", hex::encode(&changes.address))) - .is_some() - }) - .for_each(|code_change| { - let contract_change = changed_contracts - .entry(code_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: code_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&code_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, - }); - - contract_change.code.clear(); - contract_change - .code - .extend_from_slice(&code_change.new_code); - }); - - if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() { - transaction_contract_changes - .entry(block_tx.index.into()) - .or_insert_with(|| tycho::TransactionContractChanges { - tx: Some(tycho::Transaction { - hash: block_tx.hash.clone(), - from: block_tx.from.clone(), - to: block_tx.to.clone(), - index: block_tx.index as u64, - }), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - }) - .contract_changes - .extend(changed_contracts.drain().map(|(_, change)| change.into())); - } - }); -} diff --git a/substreams/ethereum-balancer/src/lib.rs b/substreams/ethereum-balancer/src/lib.rs index 88ecc50..27bd15a 100644 --- a/substreams/ethereum-balancer/src/lib.rs +++ b/substreams/ethereum-balancer/src/lib.rs @@ -1,5 +1,3 @@ mod abi; -mod contract_changes; mod modules; -mod pb; mod pool_factories; diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index c4fcb4a..9923167 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -1,27 +1,20 @@ -use std::collections::HashMap; -use std::str::FromStr; - +use crate::{abi, pool_factories}; use anyhow::Result; +use itertools::Itertools; +use std::collections::HashMap; use substreams::hex; use substreams::pb::substreams::StoreDeltas; use substreams::store::{ StoreAdd, StoreAddBigInt, StoreAddInt64, StoreGet, StoreGetInt64, StoreNew, }; - -use substreams::key; -use substreams::scalar::BigInt; - use substreams_ethereum::pb::eth; - -use itertools::Itertools; - - -use contract_changes::extract_contract_changes; use substreams_ethereum::Event; - -use crate::pb::tycho::evm::v1::{self as tycho}; -use crate::pb::tycho::evm::v1::{BalanceDelta, BlockBalanceDeltas, BlockTransactionProtocolComponents, TransactionProtocolComponents}; -use crate::{abi, contract_changes, pool_factories}; +use tycho_substreams::balances; +use tycho_substreams::contract::extract_contract_changes; +use tycho_substreams::pb::tycho::evm::v1::{ + self as tycho, BalanceDelta, BlockBalanceDeltas, BlockTransactionProtocolComponents, + TransactionProtocolComponents, +}; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -110,7 +103,13 @@ pub fn map_balance_deltas( if let Some(ev) = abi::vault::events::PoolBalanceChanged::match_and_decode(vault_log.log) { - let component_id = ev.pool_id[..20].to_vec(); + let component_id = format!( + "0x{}", + String::from_utf8(ev.pool_id[..20].to_vec()).unwrap() + ) + .as_bytes() + .to_vec(); + if store .get_last(format!("pool:{}", hex::encode(&component_id))) .is_some() @@ -131,7 +130,13 @@ pub fn map_balance_deltas( } } } else if let Some(ev) = abi::vault::events::Swap::match_and_decode(vault_log.log) { - let component_id = ev.pool_id[..20].to_vec(); + let component_id = format!( + "0x{}", + String::from_utf8(ev.pool_id[..20].to_vec()).unwrap() + ) + .as_bytes() + .to_vec(); + if store .get_last(format!("pool:{}", hex::encode(&component_id))) .is_some() @@ -176,17 +181,7 @@ pub fn map_balance_deltas( /// store key to ensure that there's a unique balance being tallied for each. #[substreams::handlers::store] pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { - deltas.balance_deltas.iter().for_each(|delta| { - store.add( - delta.ord, - format!( - "pool:{0}:token:{1}", - hex::encode(&delta.component_id), - hex::encode(&delta.token) - ), - BigInt::from_signed_bytes_be(&delta.delta), - ); - }); + balances::store_balance_changes(deltas, store); } /// This is the main map that handles most of the indexing of this substream. @@ -215,67 +210,37 @@ pub fn map_changes( .iter() .for_each(|tx_component| { let tx = tx_component.tx.as_ref().unwrap(); - transaction_contract_changes .entry(tx.index) - .or_insert_with(|| tycho::TransactionContractChanges { - tx: Some(tx.clone()), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - }) + .or_insert_with(|| tycho::TransactionContractChanges::new(&tx)) .component_changes .extend_from_slice(&tx_component.components); }); // Balance changes are gathered by the `StoreDelta` based on `PoolBalanceChanged` creating - // `BlockBalanceDeltas`. We essentially just process the changes that occured to the `store` this + // `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store` this // block. Then, these balance changes are merged onto the existing map of tx contract changes, // inserting a new one if it doesn't exist. - balance_store - .deltas + balances::aggregate_balances_changes(balance_store, deltas) .into_iter() - .zip(deltas.balance_deltas) - .map(|(store_delta, balance_delta)| { - let pool_id = key::segment_at(&store_delta.key, 1); - let token_id = key::segment_at(&store_delta.key, 3); - // store_delta.new_value is an ASCII string representing an integer - let ascii_string = - String::from_utf8(store_delta.new_value.clone()).expect("Invalid UTF-8 sequence"); - let balance = BigInt::from_str(&ascii_string).expect("Failed to parse integer"); - let big_endian_bytes_balance = balance.to_bytes_be().1; - - ( - balance_delta.tx.unwrap(), - tycho::BalanceChange { - token: hex::decode(token_id).expect("Token ID not valid hex"), - balance: big_endian_bytes_balance, - component_id: pool_id.as_bytes().to_vec(), - }, - ) - }) - // We need to group the balance changes by tx hash for the `TransactionContractChanges` agg - .group_by(|(tx, _)| TransactionWrapper(tx.clone())) - .into_iter() - .for_each(|(tx_wrapped, group)| { - let tx = tx_wrapped.0; - + .for_each(|(_, (tx, balances))| { transaction_contract_changes .entry(tx.index) - .or_insert_with(|| tycho::TransactionContractChanges { - tx: Some(tx.clone()), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - }) + .or_insert_with(|| tycho::TransactionContractChanges::new(&tx)) .balance_changes - .extend(group.map(|(_, change)| change)); + .extend(balances.into_iter().map(|(_, change)| change)); }); - // General helper for extracting contract changes. Uses block, our component store which holds - // all of our tracked deployed pool addresses, and the map of tx contract changes which we - // output into for final processing later. - extract_contract_changes(&block, components_store, &mut transaction_contract_changes); + // Extract and insert any storage changes that happened for any of the components. + extract_contract_changes( + &block, + |addr| { + components_store + .get_last(format!("pool:{0}", hex::encode(&addr))) + .is_some() + }, + &mut transaction_contract_changes, + ); // Process all `transaction_contract_changes` for final output in the `BlockContractChanges`, // sorted by transaction index (the key). diff --git a/substreams/ethereum-balancer/src/pb/mod.rs b/substreams/ethereum-balancer/src/pb/mod.rs deleted file mode 100644 index 43d8838..0000000 --- a/substreams/ethereum-balancer/src/pb/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -// @generated -pub mod tycho { - pub mod evm { - // @@protoc_insertion_point(attribute:tycho.evm.v1) - pub mod v1 { - include!("tycho.evm.v1.rs"); - // @@protoc_insertion_point(tycho.evm.v1) - } - } -} diff --git a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs b/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs deleted file mode 100644 index 387ff7b..0000000 --- a/substreams/ethereum-balancer/src/pb/tycho.evm.v1.rs +++ /dev/null @@ -1,319 +0,0 @@ -// @generated -// This file contains the proto definitions for Substreams common to all integrations. - -/// A struct describing a block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Block { - /// The blocks hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The parent blocks hash. - #[prost(bytes="vec", tag="2")] - pub parent_hash: ::prost::alloc::vec::Vec, - /// The block number. - #[prost(uint64, tag="3")] - pub number: u64, - /// The block timestamp. - #[prost(uint64, tag="4")] - pub ts: u64, -} -/// A struct describing a transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transaction { - /// The transaction hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The sender of the transaction. - #[prost(bytes="vec", tag="2")] - pub from: ::prost::alloc::vec::Vec, - /// The receiver of the transaction. - #[prost(bytes="vec", tag="3")] - pub to: ::prost::alloc::vec::Vec, - /// The transactions index within the block. - /// TODO: should this be uint32? to match the type from the native substream type? - #[prost(uint64, tag="4")] - pub index: u64, -} -/// A custom struct representing an arbitrary attribute of a protocol component. -/// This is mainly used by the native integration to track the necessary information about the protocol. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Attribute { - /// The name of the attribute. - #[prost(string, tag="1")] - pub name: ::prost::alloc::string::String, - /// The value of the attribute. - #[prost(bytes="vec", tag="2")] - pub value: ::prost::alloc::vec::Vec, - /// The type of change the attribute underwent. - #[prost(enumeration="ChangeType", tag="3")] - pub change: i32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProtocolType { - #[prost(string, tag="1")] - pub name: ::prost::alloc::string::String, - #[prost(enumeration="FinancialType", tag="2")] - pub financial_type: i32, - #[prost(message, repeated, tag="3")] - pub attribute_schema: ::prost::alloc::vec::Vec, - #[prost(enumeration="ImplementationType", tag="4")] - pub implementation_type: i32, -} -/// A struct describing a part of the protocol. -/// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, -/// the component would represent a single contract. In case of VM integration, such component would -/// not need any attributes, because all the relevant info would be tracked via storage slots and balance changes. -/// It can also be a wrapping contract, like WETH, that has a constant price, but it allows swapping tokens. -/// This is why the name ProtocolComponent is used instead of "Pool" or "Pair". -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProtocolComponent { - /// A unique identifier for the component within the protocol. - /// Can be e.g. a stringified address or a string describing the trading pair. - #[prost(string, tag="1")] - pub id: ::prost::alloc::string::String, - /// Addresses of the ERC20 tokens used by the component. - #[prost(bytes="vec", repeated, tag="2")] - pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Addresses of the contracts used by the component. - /// Usually it is a single contract, but some protocols use multiple contracts. - #[prost(bytes="vec", repeated, tag="3")] - pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Attributes of the component. Used mainly be the native integration. - /// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. - #[prost(message, repeated, tag="4")] - pub static_att: ::prost::alloc::vec::Vec, - /// Type of change the component underwent. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, - /// / Represents the functionality of the component. - #[prost(message, optional, tag="6")] - pub protocol_type: ::core::option::Option, - /// Transaction where this component was created - #[prost(message, optional, tag="7")] - pub tx: ::core::option::Option, -} -/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -/// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceChange { - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="1")] - pub token: ::prost::alloc::vec::Vec, - /// The new balance of the token. Note: it must be a big endian encoded int. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. - /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. - #[prost(bytes="vec", tag="3")] - pub component_id: ::prost::alloc::vec::Vec, -} -/// Enum to specify the type of a change. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum ChangeType { - Unspecified = 0, - Update = 1, - Creation = 2, - Deletion = 3, -} -impl ChangeType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED", - ChangeType::Update => "CHANGE_TYPE_UPDATE", - ChangeType::Creation => "CHANGE_TYPE_CREATION", - ChangeType::Deletion => "CHANGE_TYPE_DELETION", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "CHANGE_TYPE_UPDATE" => Some(Self::Update), - "CHANGE_TYPE_CREATION" => Some(Self::Creation), - "CHANGE_TYPE_DELETION" => Some(Self::Deletion), - _ => None, - } - } -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum FinancialType { - Swap = 0, - Lend = 1, - Leverage = 2, - Psm = 3, -} -impl FinancialType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - FinancialType::Swap => "SWAP", - FinancialType::Lend => "LEND", - FinancialType::Leverage => "LEVERAGE", - FinancialType::Psm => "PSM", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "SWAP" => Some(Self::Swap), - "LEND" => Some(Self::Lend), - "LEVERAGE" => Some(Self::Leverage), - "PSM" => Some(Self::Psm), - _ => None, - } - } -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum ImplementationType { - Vm = 0, - Custom = 1, -} -impl ImplementationType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - ImplementationType::Vm => "VM", - ImplementationType::Custom => "CUSTOM", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "VM" => Some(Self::Vm), - "CUSTOM" => Some(Self::Custom), - _ => None, - } - } -} -// This file contains proto definitions specific to the VM integration. - -/// A key value entry into contract storage. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractSlot { - /// A contract's storage slot. - #[prost(bytes="vec", tag="2")] - pub slot: ::prost::alloc::vec::Vec, - /// The new value for this storage slot. - #[prost(bytes="vec", tag="3")] - pub value: ::prost::alloc::vec::Vec, -} -/// Changes made to a single contract's state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractChange { - /// The contract's address - #[prost(bytes="vec", tag="1")] - pub address: ::prost::alloc::vec::Vec, - /// The new native balance of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The new code of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="3")] - pub code: ::prost::alloc::vec::Vec, - /// The changes to this contract's slots, empty sequence indicates no change. - #[prost(message, repeated, tag="4")] - pub slots: ::prost::alloc::vec::Vec, - /// Whether this is an update, a creation or a deletion. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, -} -/// A set of changes aggregated by transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionContractChanges { - /// The transaction instance that results in the changes. - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - /// Contains the changes induced by the above transaction, aggregated on a per-contract basis. - /// Must include changes to every contract that is tracked by all ProtocolComponents. - #[prost(message, repeated, tag="2")] - pub contract_changes: ::prost::alloc::vec::Vec, - /// An array of any component changes. - #[prost(message, repeated, tag="3")] - pub component_changes: ::prost::alloc::vec::Vec, - /// An array of balance changes to components. - #[prost(message, repeated, tag="4")] - pub balance_changes: ::prost::alloc::vec::Vec, -} -/// A set of transaction changes within a single block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockContractChanges { - /// The block for which these changes are collectively computed. - #[prost(message, optional, tag="1")] - pub block: ::core::option::Option, - /// The set of transaction changes observed in the specified block. - #[prost(message, repeated, tag="2")] - pub changes: ::prost::alloc::vec::Vec, -} -/// A message containing relative balance changes. -/// -/// Used to track token balances of protocol components in case they are only -/// available as relative values within a block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceDelta { - /// The ordinal of the balance change. Must be unique & deterministic over all balances - /// changes within a block. - #[prost(uint64, tag="1")] - pub ord: u64, - /// The tx hash of the transaction that caused the balance change. - #[prost(message, optional, tag="2")] - pub tx: ::core::option::Option, - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="3")] - pub token: ::prost::alloc::vec::Vec, - /// The delta balance of the token. - #[prost(bytes="vec", tag="4")] - pub delta: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - /// If the protocol component includes multiple contracts, the balance change must be - /// aggregated to reflect how much tokens can be traded. - #[prost(bytes="vec", tag="5")] - pub component_id: ::prost::alloc::vec::Vec, -} -/// A set of balances deltas, usually a group of changes within a single block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockBalanceDeltas { - #[prost(message, repeated, tag="1")] - pub balance_deltas: ::prost::alloc::vec::Vec, -} -/// A message containing protocol components that were created by a single tx. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionProtocolComponents { - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - #[prost(message, repeated, tag="2")] - pub components: ::prost::alloc::vec::Vec, -} -/// All protocol components that were created within a block with their corresponding tx. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockTransactionProtocolComponents { - #[prost(message, repeated, tag="1")] - pub tx_components: ::prost::alloc::vec::Vec, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index e19933c..27c5ced 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -2,10 +2,10 @@ use substreams_ethereum::pb::eth::v2::{Call, Log}; use substreams_ethereum::{Event, Function}; use crate::abi; -use crate::pb; -use crate::pb::tycho::evm::v1::{FinancialType, ImplementationType, ProtocolType, Transaction}; -use pb::tycho::evm::v1::{self as tycho}; use substreams::hex; +use tycho_substreams::pb::tycho::evm::v1::{ + self as tycho, FinancialType, ImplementationType, ProtocolType, Transaction, +}; use substreams::scalar::BigInt; From 18e9dfcec497aea9715671e5df65086ca2ca3bb4 Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 21:07:46 +0000 Subject: [PATCH 17/37] Remove TransactionWrapper from SDK & Balancer. This type is not needed anymore. --- crates/tycho-substreams/src/lib.rs | 2 -- crates/tycho-substreams/src/utils.rs | 24 --------------------- substreams/ethereum-balancer/src/modules.rs | 11 ---------- 3 files changed, 37 deletions(-) delete mode 100644 crates/tycho-substreams/src/utils.rs diff --git a/crates/tycho-substreams/src/lib.rs b/crates/tycho-substreams/src/lib.rs index d5b0d0f..78c7e2e 100644 --- a/crates/tycho-substreams/src/lib.rs +++ b/crates/tycho-substreams/src/lib.rs @@ -2,5 +2,3 @@ pub mod balances; pub mod contract; mod mock_store; pub mod pb; -// TODO: consider removing this module, after integrating with balancer -pub mod utils; diff --git a/crates/tycho-substreams/src/utils.rs b/crates/tycho-substreams/src/utils.rs deleted file mode 100644 index e4729db..0000000 --- a/crates/tycho-substreams/src/utils.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::pb::tycho::evm::v1::Transaction; - -/// This struct purely exists to spoof the `PartialEq` trait for `Transaction` so we can use it in -/// a later groupby operation. -#[derive(Debug)] -pub struct TransactionWrapper(Transaction); - -impl TransactionWrapper { - pub fn new(tx: Transaction) -> Self { - Self(tx) - } -} - -impl PartialEq for TransactionWrapper { - fn eq(&self, other: &Self) -> bool { - self.0.hash == other.0.hash - } -} - -impl From for Transaction { - fn from(value: TransactionWrapper) -> Self { - value.0 - } -} diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 9923167..a3658ad 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -18,17 +18,6 @@ use tycho_substreams::pb::tycho::evm::v1::{ const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); -/// This struct purely exists to spoof the `PartialEq` trait for `Transaction` so we can use it in -/// a later groupby operation. -#[derive(Debug)] -struct TransactionWrapper(tycho::Transaction); - -impl PartialEq for TransactionWrapper { - fn eq(&self, other: &Self) -> bool { - self.0.hash == other.0.hash - } -} - #[substreams::handlers::map] pub fn map_pools_created(block: eth::v2::Block) -> Result { // Gather contract changes by indexing `PoolCreated` events and analysing the `Create` call From 312d322585f2e2dd91bf2f11e43ed56614f569a1 Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 22:10:54 +0000 Subject: [PATCH 18/37] Add tycho pb type constructors. This allows us to remove a lot of unnecessary boilerplate code. --- crates/tycho-substreams/src/contract.rs | 87 +++--- crates/tycho-substreams/src/pb/mod.rs | 99 +++++++ substreams/ethereum-balancer/src/modules.rs | 47 +--- .../ethereum-balancer/src/pool_factories.rs | 261 ++++++------------ 4 files changed, 228 insertions(+), 266 deletions(-) diff --git a/crates/tycho-substreams/src/contract.rs b/crates/tycho-substreams/src/contract.rs index 79ad454..633ef35 100644 --- a/crates/tycho-substreams/src/contract.rs +++ b/crates/tycho-substreams/src/contract.rs @@ -7,6 +7,7 @@ use std::collections::HashMap; use substreams_ethereum::pb::eth; +use substreams_ethereum::pb::eth::v2::StorageChange; use crate::pb::tycho::evm::v1::{self as tycho}; @@ -15,6 +16,12 @@ struct SlotValue { start_value: Vec, } +impl From<&StorageChange> for SlotValue { + fn from(change: &StorageChange) -> Self { + Self { new_value: change.new_value.clone(), start_value: change.old_value.clone() } + } +} + impl SlotValue { fn has_changed(&self) -> bool { self.start_value != self.new_value @@ -30,6 +37,22 @@ struct InterimContractChange { change: tycho::ChangeType, } +impl InterimContractChange { + fn new(address: &[u8], creation: bool) -> Self { + Self { + address: address.to_vec(), + balance: vec![], + code: vec![], + slots: Default::default(), + change: if creation { + tycho::ChangeType::Creation.into() + } else { + tycho::ChangeType::Update.into() + }, + } + } +} + impl From for tycho::ContractChange { fn from(value: InterimContractChange) -> Self { tycho::ContractChange { @@ -90,28 +113,20 @@ pub fn extract_contract_changes bool>( storage_changes .iter() .filter(|changes| inclusion_predicate(&changes.address)) - .for_each(|storage_change| { + .for_each(|&storage_change| { let contract_change = changed_contracts .entry(storage_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: storage_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&storage_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, + .or_insert_with(|| { + InterimContractChange::new( + &storage_change.address, + created_accounts.contains_key(&storage_change.address), + ) }); let slot_value = contract_change .slots .entry(storage_change.key.clone()) - .or_insert_with(|| SlotValue { - new_value: storage_change.new_value.clone(), - start_value: storage_change.old_value.clone(), - }); + .or_insert_with(|| storage_change.into()); slot_value .new_value @@ -124,16 +139,11 @@ pub fn extract_contract_changes bool>( .for_each(|balance_change| { let contract_change = changed_contracts .entry(balance_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: balance_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&balance_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, + .or_insert_with(|| { + InterimContractChange::new( + &balance_change.address, + created_accounts.contains_key(&balance_change.address), + ) }); if let Some(new_balance) = &balance_change.new_value { @@ -150,16 +160,11 @@ pub fn extract_contract_changes bool>( .for_each(|code_change| { let contract_change = changed_contracts .entry(code_change.address.clone()) - .or_insert_with(|| InterimContractChange { - address: code_change.address.clone(), - balance: Vec::new(), - code: Vec::new(), - slots: HashMap::new(), - change: if created_accounts.contains_key(&code_change.address) { - tycho::ChangeType::Creation - } else { - tycho::ChangeType::Update - }, + .or_insert_with(|| { + InterimContractChange::new( + &code_change.address, + created_accounts.contains_key(&code_change.address), + ) }); contract_change.code.clear(); @@ -174,17 +179,7 @@ pub fn extract_contract_changes bool>( { transaction_contract_changes .entry(block_tx.index.into()) - .or_insert_with(|| tycho::TransactionContractChanges { - tx: Some(tycho::Transaction { - hash: block_tx.hash.clone(), - from: block_tx.from.clone(), - to: block_tx.to.clone(), - index: block_tx.index as u64, - }), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - }) + .or_insert_with(|| tycho::TransactionContractChanges::new(&(block_tx.into()))) .contract_changes .extend( changed_contracts diff --git a/crates/tycho-substreams/src/pb/mod.rs b/crates/tycho-substreams/src/pb/mod.rs index f5cd0b0..ceced59 100644 --- a/crates/tycho-substreams/src/pb/mod.rs +++ b/crates/tycho-substreams/src/pb/mod.rs @@ -3,6 +3,7 @@ pub mod tycho { pub mod evm { // @@protoc_insertion_point(attribute:tycho.evm.v1) pub mod v1 { + use substreams_ethereum::pb::eth::v2::{self as sf}; include!("tycho.evm.v1.rs"); // @@protoc_insertion_point(tycho.evm.v1) @@ -16,6 +17,104 @@ pub mod tycho { } } } + + impl From<&sf::TransactionTrace> for Transaction { + fn from(tx: &sf::TransactionTrace) -> Self { + Self { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + } + } + } + + impl From<&sf::Block> for Block { + fn from(block: &sf::Block) -> Self { + Self { + number: block.number, + hash: block.hash.clone(), + parent_hash: block + .header + .as_ref() + .expect("Block header not present") + .parent_hash + .clone(), + ts: block.timestamp_seconds(), + } + } + } + + impl ProtocolComponent { + pub fn new(id: &str, tx: &Transaction) -> Self { + Self { + id: id.to_string(), + tokens: vec![], + contracts: vec![], + static_att: vec![], + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { + Self { + id: format!("0x{}", hex::encode(id)), + tokens: vec![], + contracts: vec![id.to_vec()], + static_att: vec![], + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + pub fn with_tokens>(mut self, tokens: &[B]) -> Self { + self.tokens = tokens + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + pub fn with_contracts>(mut self, contracts: &[B]) -> Self { + self.contracts = contracts + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + pub fn with_attributes, V: AsRef<[u8]>>( + mut self, + attributes: &[(K, V)], + ) -> Self { + self.static_att = attributes + .iter() + .map(|(k, v)| Attribute { + name: k.as_ref().to_string(), + value: v.as_ref().to_vec(), + change: ChangeType::Creation.into(), + }) + .collect::>(); + self + } + + pub fn as_swap_type( + mut self, + name: &str, + implementation_type: ImplementationType, + ) -> Self { + self.protocol_type = Some(ProtocolType { + name: name.to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: implementation_type.into(), + }); + self + } + } } } } diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index a3658ad..81411f4 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -34,24 +34,14 @@ pub fn map_pools_created(block: eth::v2::Block) -> Result>(); if !components.is_empty() { Some(TransactionProtocolComponents { - tx: Some(tycho::Transaction { - hash: tx.hash.clone(), - from: tx.from.clone(), - to: tx.to.clone(), - index: Into::::into(tx.index), - }), + tx: Some(tx.into()), components, }) } else { @@ -106,12 +96,7 @@ pub fn map_balance_deltas( for (token, delta) in ev.tokens.iter().zip(ev.deltas.iter()) { deltas.push(BalanceDelta { ord: vault_log.ordinal(), - tx: Some(tycho::Transaction { - hash: vault_log.receipt.transaction.hash.clone(), - from: vault_log.receipt.transaction.from.clone(), - to: vault_log.receipt.transaction.to.clone(), - index: vault_log.receipt.transaction.index.into(), - }), + tx: Some(vault_log.receipt.transaction.into()), token: token.to_vec(), delta: delta.to_signed_bytes_be(), component_id: component_id.clone(), @@ -133,24 +118,14 @@ pub fn map_balance_deltas( deltas.extend_from_slice(&[ BalanceDelta { ord: vault_log.ordinal(), - tx: Some(tycho::Transaction { - hash: vault_log.receipt.transaction.hash.clone(), - from: vault_log.receipt.transaction.from.clone(), - to: vault_log.receipt.transaction.to.clone(), - index: vault_log.receipt.transaction.index.into(), - }), + tx: Some(vault_log.receipt.transaction.into()), token: ev.token_in.to_vec(), delta: ev.amount_in.to_signed_bytes_be(), component_id: component_id.clone(), }, BalanceDelta { ord: vault_log.ordinal(), - tx: Some(tycho::Transaction { - hash: vault_log.receipt.transaction.hash.clone(), - from: vault_log.receipt.transaction.from.clone(), - to: vault_log.receipt.transaction.to.clone(), - index: vault_log.receipt.transaction.index.into(), - }), + tx: Some(vault_log.receipt.transaction.into()), token: ev.token_out.to_vec(), delta: ev.amount_out.neg().to_signed_bytes_be(), component_id, @@ -234,17 +209,7 @@ pub fn map_changes( // Process all `transaction_contract_changes` for final output in the `BlockContractChanges`, // sorted by transaction index (the key). Ok(tycho::BlockContractChanges { - block: Some(tycho::Block { - number: block.number, - hash: block.hash.clone(), - parent_hash: block - .header - .as_ref() - .expect("Block header not present") - .parent_hash - .clone(), - ts: block.timestamp_seconds(), - }), + block: Some((&block).into()), changes: transaction_contract_changes .drain() .sorted_unstable_by_key(|(index, _)| *index) diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index 27c5ced..2ef1bc8 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -3,9 +3,7 @@ use substreams_ethereum::{Event, Function}; use crate::abi; use substreams::hex; -use tycho_substreams::pb::tycho::evm::v1::{ - self as tycho, FinancialType, ImplementationType, ProtocolType, Transaction, -}; +use tycho_substreams::pb::tycho::evm::v1::{ImplementationType, ProtocolComponent, Transaction}; use substreams::scalar::BigInt; @@ -39,16 +37,16 @@ impl SerializableVecBigInt for Vec { /// - Stable Pool Factories /// (Balancer does have a bit more (esp. in the deprecated section) that could be implemented as /// desired.) -/// We use the specific ABIs to decode both the log event and cooresponding call to gather -/// `PoolCreated` event information alongside the `Create` calldata that provide us details to -/// fufill both the required details + any extra `Attributes` +/// We use the specific ABIs to decode both the log event and corresponding call to gather +/// `PoolCreated` event information alongside the `Create` call data that provide us details to +/// fulfill both the required details + any extra `Attributes` /// Ref: https://docs.balancer.fi/reference/contracts/deployment-addresses/mainnet.html pub fn address_map( pool_factory_address: &[u8], log: &Log, call: &Call, tx: &Transaction, -) -> Option { +) -> Option { match *pool_factory_address { hex!("897888115Ada5773E02aA29F775430BFB5F34c51") => { let create_call = @@ -56,31 +54,18 @@ pub fn address_map( let pool_created = abi::weighted_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: create_call.tokens, - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "WeightedPoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "normalized_weights".into(), - value: create_call.normalized_weights.serialize_bytes(), - change: tycho::ChangeType::Creation.into(), - }, - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[ + ("pool_type", "WeightedPoolFactory".as_bytes()), + ( + "normalized_weights", + &create_call.normalized_weights.serialize_bytes(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } hex!("DB8d758BCb971e482B2C45f7F8a7740283A1bd3A") => { let create_call = @@ -88,24 +73,12 @@ pub fn address_map( let pool_created = abi::composable_stable_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: create_call.tokens, - contracts: vec![pool_created.pool], - static_att: vec![tycho::Attribute { - name: "pool_type".into(), - value: "ComposableStablePoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[("pool_type", "ComposableStablePoolFactory".as_bytes())]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } hex!("813EE7a840CE909E7Fea2117A44a90b8063bd4fd") => { let create_call = @@ -113,33 +86,18 @@ pub fn address_map( let pool_created = abi::erc_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "ERC4626LinearPoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "upper_target".into(), - value: create_call.upper_target.to_signed_bytes_be(), - change: tycho::ChangeType::Creation.into(), - }, - // Note, `lower_target` is generally hardcoded for all pools, not located in call data - // Note, rate provider might be provided as `create.protocol_id`, but as a BigInt. needs investigation - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "ERC4626LinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call.upper_target.to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } hex!("5F43FBa61f63Fa6bFF101a0A0458cEA917f6B347") => { let create_call = @@ -147,31 +105,18 @@ pub fn address_map( let pool_created = abi::euler_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "EulerLinearPoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "upper_target".into(), - value: create_call.upper_target.to_signed_bytes_be(), - change: tycho::ChangeType::Creation.into(), - }, - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "EulerLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call.upper_target.to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } // ❌ Reading the deployed factory for Gearbox showcases that it's currently disabled // hex!("39A79EB449Fc05C92c39aA6f0e9BfaC03BE8dE5B") => { @@ -226,31 +171,18 @@ pub fn address_map( let pool_created = abi::silo_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "SiloLinearPoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "upper_target".into(), - value: create_call.upper_target.to_signed_bytes_be(), - change: tycho::ChangeType::Creation.into(), - }, - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "SiloLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call.upper_target.to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } hex!("5F5222Ffa40F2AEd6380D022184D6ea67C776eE0") => { let create_call = @@ -258,65 +190,36 @@ pub fn address_map( let pool_created = abi::yearn_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: vec![create_call.main_token, create_call.wrapped_token], - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "YearnLinearPoolFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "upper_target".into(), - value: create_call.upper_target.to_signed_bytes_be(), - change: tycho::ChangeType::Creation.into(), - }, - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "YearnLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call.upper_target.to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } - // The `WeightedPool2TokenFactory` is a deprecated contract but we've included it since one - // of the highest TVL pools, 80BAL-20WETH, is able to be tracked. + // The `WeightedPool2TokenFactory` is a deprecated contract, but we've included + // it to be able to track one of the highest TVL pools: 80BAL-20WETH. hex!("A5bf2ddF098bb0Ef6d120C98217dD6B141c74EE0") => { let create_call = abi::weighted_pool_tokens_factory::functions::Create::match_and_decode(call)?; let pool_created = abi::weighted_pool_tokens_factory::events::PoolCreated::match_and_decode(log)?; - Some(tycho::ProtocolComponent { - id: hex::encode(&pool_created.pool), - tokens: create_call.tokens, - contracts: vec![pool_created.pool], - static_att: vec![ - tycho::Attribute { - name: "pool_type".into(), - value: "WeightedPool2TokensFactory".into(), - change: tycho::ChangeType::Creation.into(), - }, - tycho::Attribute { - name: "weights".into(), - value: create_call.weights.serialize_bytes(), - change: tycho::ChangeType::Creation.into(), - }, - ], - change: tycho::ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "balancer_pool".to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: ImplementationType::Vm.into(), - }), - tx: Some(tx.clone()), - }) + Some( + ProtocolComponent::at_contract(&pool_created.pool, &tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[ + ("pool_type", "WeightedPool2TokensFactory".as_bytes()), + ("weights", &create_call.weights.serialize_bytes()), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) } _ => None, } From cfdb31b0c5c470ae665a85a3fe9624c492217e4f Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 23:12:30 +0000 Subject: [PATCH 19/37] Add documentation for the main methods added. --- crates/tycho-substreams/src/balances.rs | 30 +++++++++++++++++++++++++ crates/tycho-substreams/src/contract.rs | 28 +++++++++++++++++++---- crates/tycho-substreams/src/pb/mod.rs | 17 ++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/crates/tycho-substreams/src/balances.rs b/crates/tycho-substreams/src/balances.rs index 2547723..66ff2b5 100644 --- a/crates/tycho-substreams/src/balances.rs +++ b/crates/tycho-substreams/src/balances.rs @@ -19,6 +19,20 @@ use substreams::key; use substreams::pb::substreams::StoreDeltas; use substreams::prelude::{BigInt, StoreAdd}; +/// Store relative balances changes in a additive manner. +/// +/// Effectively aggregates the relative balances changes into an absolute balances. +/// +/// ## Arguments +/// +/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. +/// Note: relative balance deltas must have strictly increasing ordinals per token +/// address, will panic otherwise. +/// * `store` - An AddStore that will add relative balance changes. +/// +/// This method is meant to be used in combination with `aggregate_balances_changes` +/// which consumes the store filled with this methods in +/// [deltas mode](https://substreams.streamingfast.io/documentation/develop/manifest-modules/types#deltas-mode). pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd) { let mut previous_ordinal = HashMap::::new(); deltas @@ -49,6 +63,22 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd for tycho::ContractChange { } } +/// Extracts relevant contract changes from the block. +/// +/// Contract changes include changes in storage, code and native balance. +/// +/// ## Arguments +/// +/// * `block` - The block to extract changes from. Must be the extended block model. +/// * `inclusion_predicate` - A predicate function that determines if a contract address is relevant. +/// * `transaction_contract_changes` - A mutable map to store the contract changes in. +/// +/// ## Panics +/// Will panic in case the detail level of the block is not extended. pub fn extract_contract_changes bool>( block: ð::v2::Block, inclusion_predicate: F, transaction_contract_changes: &mut HashMap, ) { + if block.detail_level != Into::::into(DetailLevel::DetaillevelExtended) { + panic!("Only extended blocks are supported"); + } let mut changed_contracts: HashMap, InterimContractChange> = HashMap::new(); // Collect all accounts created in this block diff --git a/crates/tycho-substreams/src/pb/mod.rs b/crates/tycho-substreams/src/pb/mod.rs index ceced59..5e6abdd 100644 --- a/crates/tycho-substreams/src/pb/mod.rs +++ b/crates/tycho-substreams/src/pb/mod.rs @@ -8,6 +8,7 @@ pub mod tycho { // @@protoc_insertion_point(tycho.evm.v1) impl TransactionContractChanges { + /// Creates a new empty `TransactionContractChanges` instance. pub fn new(tx: &Transaction) -> Self { Self { tx: Some(tx.clone()), @@ -46,6 +47,9 @@ pub mod tycho { } impl ProtocolComponent { + /// Creates a new empty `ProtocolComponent` instance. + /// + /// You can use the `with_*` methods to set the fields in a convience way. pub fn new(id: &str, tx: &Transaction) -> Self { Self { id: id.to_string(), @@ -58,6 +62,10 @@ pub mod tycho { } } + /// Shorthand to create a component with a 1-1 relationship to a contract. + /// + /// Will set the component id to a hex encoded address with a 0x prefix + /// and add the contract to contracts attributes. pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { Self { id: format!("0x{}", hex::encode(id)), @@ -70,6 +78,7 @@ pub mod tycho { } } + /// Replaces the tokens on this component. pub fn with_tokens>(mut self, tokens: &[B]) -> Self { self.tokens = tokens .iter() @@ -78,6 +87,7 @@ pub mod tycho { self } + /// Replaces the contracts associated with this component. pub fn with_contracts>(mut self, contracts: &[B]) -> Self { self.contracts = contracts .iter() @@ -86,6 +96,9 @@ pub mod tycho { self } + /// Replaces the static attributes on this component. + /// + /// The change type will be set to Creation. pub fn with_attributes, V: AsRef<[u8]>>( mut self, attributes: &[(K, V)], @@ -101,6 +114,10 @@ pub mod tycho { self } + /// Sets the protocol_type on this component. + /// + /// Will set the `financial_type` to FinancialType::Swap and the + /// `attribute_schema` to an empty list. pub fn as_swap_type( mut self, name: &str, From ba2a4ced08a4da23da2be668c3bc5f9c95995444 Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 23:19:45 +0000 Subject: [PATCH 20/37] Use expect instead of unwrap. --- crates/tycho-substreams/src/balances.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/tycho-substreams/src/balances.rs b/crates/tycho-substreams/src/balances.rs index 66ff2b5..8046fe1 100644 --- a/crates/tycho-substreams/src/balances.rs +++ b/crates/tycho-substreams/src/balances.rs @@ -97,7 +97,9 @@ pub fn aggregate_balances_changes( let big_endian_bytes_balance = balance.to_bytes_be().1; ( - balance_delta.tx.unwrap(), + balance_delta + .tx + .expect("Missing transaction on delta"), BalanceChange { token: hex::decode(token_id).expect("Token ID not valid hex"), balance: big_endian_bytes_balance, From 29e5984a3a8be00a77f0efe9eb095d8e6f1e31fb Mon Sep 17 00:00:00 2001 From: kayibal Date: Wed, 13 Mar 2024 23:49:40 +0000 Subject: [PATCH 21/37] Add prelude; Move pb implementations. Else the implementations would get overwritten. --- crates/tycho-substreams/src/lib.rs | 7 +- crates/tycho-substreams/src/models.rs | 123 +++++++++++++++++ crates/tycho-substreams/src/pb/mod.rs | 127 ------------------ substreams/ethereum-balancer/src/modules.rs | 22 ++- .../ethereum-balancer/src/pool_factories.rs | 8 +- 5 files changed, 141 insertions(+), 146 deletions(-) create mode 100644 crates/tycho-substreams/src/models.rs diff --git a/crates/tycho-substreams/src/lib.rs b/crates/tycho-substreams/src/lib.rs index 78c7e2e..03e9e03 100644 --- a/crates/tycho-substreams/src/lib.rs +++ b/crates/tycho-substreams/src/lib.rs @@ -1,4 +1,9 @@ pub mod balances; pub mod contract; mod mock_store; -pub mod pb; +pub mod models; +mod pb; + +pub mod prelude { + pub use super::models::*; +} diff --git a/crates/tycho-substreams/src/models.rs b/crates/tycho-substreams/src/models.rs new file mode 100644 index 0000000..14ab6f5 --- /dev/null +++ b/crates/tycho-substreams/src/models.rs @@ -0,0 +1,123 @@ +use substreams_ethereum::pb::eth::v2::{self as sf}; + +// re-export the protobuf types here. +pub use crate::pb::tycho::evm::v1::*; + +impl TransactionContractChanges { + /// Creates a new empty `TransactionContractChanges` instance. + pub fn new(tx: &Transaction) -> Self { + Self { + tx: Some(tx.clone()), + contract_changes: vec![], + component_changes: vec![], + balance_changes: vec![], + } + } +} + +impl From<&sf::TransactionTrace> for Transaction { + fn from(tx: &sf::TransactionTrace) -> Self { + Self { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + } + } +} + +impl From<&sf::Block> for Block { + fn from(block: &sf::Block) -> Self { + Self { + number: block.number, + hash: block.hash.clone(), + parent_hash: block + .header + .as_ref() + .expect("Block header not present") + .parent_hash + .clone(), + ts: block.timestamp_seconds(), + } + } +} + +impl ProtocolComponent { + /// Creates a new empty `ProtocolComponent` instance. + /// + /// You can use the `with_*` methods to set the fields in a convience way. + pub fn new(id: &str, tx: &Transaction) -> Self { + Self { + id: id.to_string(), + tokens: vec![], + contracts: vec![], + static_att: vec![], + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + /// Shorthand to create a component with a 1-1 relationship to a contract. + /// + /// Will set the component id to a hex encoded address with a 0x prefix + /// and add the contract to contracts attributes. + pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { + Self { + id: format!("0x{}", hex::encode(id)), + tokens: vec![], + contracts: vec![id.to_vec()], + static_att: vec![], + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + /// Replaces the tokens on this component. + pub fn with_tokens>(mut self, tokens: &[B]) -> Self { + self.tokens = tokens + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + /// Replaces the contracts associated with this component. + pub fn with_contracts>(mut self, contracts: &[B]) -> Self { + self.contracts = contracts + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + /// Replaces the static attributes on this component. + /// + /// The change type will be set to Creation. + pub fn with_attributes, V: AsRef<[u8]>>(mut self, attributes: &[(K, V)]) -> Self { + self.static_att = attributes + .iter() + .map(|(k, v)| Attribute { + name: k.as_ref().to_string(), + value: v.as_ref().to_vec(), + change: ChangeType::Creation.into(), + }) + .collect::>(); + self + } + + /// Sets the protocol_type on this component. + /// + /// Will set the `financial_type` to FinancialType::Swap and the + /// `attribute_schema` to an empty list. + pub fn as_swap_type(mut self, name: &str, implementation_type: ImplementationType) -> Self { + self.protocol_type = Some(ProtocolType { + name: name.to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: vec![], + implementation_type: implementation_type.into(), + }); + self + } +} diff --git a/crates/tycho-substreams/src/pb/mod.rs b/crates/tycho-substreams/src/pb/mod.rs index 5e6abdd..43d8838 100644 --- a/crates/tycho-substreams/src/pb/mod.rs +++ b/crates/tycho-substreams/src/pb/mod.rs @@ -3,135 +3,8 @@ pub mod tycho { pub mod evm { // @@protoc_insertion_point(attribute:tycho.evm.v1) pub mod v1 { - use substreams_ethereum::pb::eth::v2::{self as sf}; include!("tycho.evm.v1.rs"); // @@protoc_insertion_point(tycho.evm.v1) - - impl TransactionContractChanges { - /// Creates a new empty `TransactionContractChanges` instance. - pub fn new(tx: &Transaction) -> Self { - Self { - tx: Some(tx.clone()), - contract_changes: vec![], - component_changes: vec![], - balance_changes: vec![], - } - } - } - - impl From<&sf::TransactionTrace> for Transaction { - fn from(tx: &sf::TransactionTrace) -> Self { - Self { - hash: tx.hash.clone(), - from: tx.from.clone(), - to: tx.to.clone(), - index: tx.index.into(), - } - } - } - - impl From<&sf::Block> for Block { - fn from(block: &sf::Block) -> Self { - Self { - number: block.number, - hash: block.hash.clone(), - parent_hash: block - .header - .as_ref() - .expect("Block header not present") - .parent_hash - .clone(), - ts: block.timestamp_seconds(), - } - } - } - - impl ProtocolComponent { - /// Creates a new empty `ProtocolComponent` instance. - /// - /// You can use the `with_*` methods to set the fields in a convience way. - pub fn new(id: &str, tx: &Transaction) -> Self { - Self { - id: id.to_string(), - tokens: vec![], - contracts: vec![], - static_att: vec![], - change: ChangeType::Creation.into(), - protocol_type: None, - tx: Some(tx.clone()), - } - } - - /// Shorthand to create a component with a 1-1 relationship to a contract. - /// - /// Will set the component id to a hex encoded address with a 0x prefix - /// and add the contract to contracts attributes. - pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { - Self { - id: format!("0x{}", hex::encode(id)), - tokens: vec![], - contracts: vec![id.to_vec()], - static_att: vec![], - change: ChangeType::Creation.into(), - protocol_type: None, - tx: Some(tx.clone()), - } - } - - /// Replaces the tokens on this component. - pub fn with_tokens>(mut self, tokens: &[B]) -> Self { - self.tokens = tokens - .iter() - .map(|e| e.as_ref().to_vec()) - .collect::>>(); - self - } - - /// Replaces the contracts associated with this component. - pub fn with_contracts>(mut self, contracts: &[B]) -> Self { - self.contracts = contracts - .iter() - .map(|e| e.as_ref().to_vec()) - .collect::>>(); - self - } - - /// Replaces the static attributes on this component. - /// - /// The change type will be set to Creation. - pub fn with_attributes, V: AsRef<[u8]>>( - mut self, - attributes: &[(K, V)], - ) -> Self { - self.static_att = attributes - .iter() - .map(|(k, v)| Attribute { - name: k.as_ref().to_string(), - value: v.as_ref().to_vec(), - change: ChangeType::Creation.into(), - }) - .collect::>(); - self - } - - /// Sets the protocol_type on this component. - /// - /// Will set the `financial_type` to FinancialType::Swap and the - /// `attribute_schema` to an empty list. - pub fn as_swap_type( - mut self, - name: &str, - implementation_type: ImplementationType, - ) -> Self { - self.protocol_type = Some(ProtocolType { - name: name.to_string(), - financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], - implementation_type: implementation_type.into(), - }); - self - } - } } } } diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 81411f4..728a53e 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -9,12 +9,9 @@ use substreams::store::{ }; use substreams_ethereum::pb::eth; use substreams_ethereum::Event; -use tycho_substreams::balances; +use tycho_substreams::balances::aggregate_balances_changes; use tycho_substreams::contract::extract_contract_changes; -use tycho_substreams::pb::tycho::evm::v1::{ - self as tycho, BalanceDelta, BlockBalanceDeltas, BlockTransactionProtocolComponents, - TransactionProtocolComponents, -}; +use tycho_substreams::prelude::*; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -145,7 +142,7 @@ pub fn map_balance_deltas( /// store key to ensure that there's a unique balance being tallied for each. #[substreams::handlers::store] pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { - balances::store_balance_changes(deltas, store); + tycho_substreams::balances::store_balance_changes(deltas, store); } /// This is the main map that handles most of the indexing of this substream. @@ -161,11 +158,10 @@ pub fn map_changes( deltas: BlockBalanceDeltas, components_store: StoreGetInt64, balance_store: StoreDeltas, // Note, this map module is using the `deltas` mode for the store. -) -> Result { +) -> Result { // We merge contract changes by transaction (identified by transaction index) making it easy to // sort them at the very end. - let mut transaction_contract_changes: HashMap<_, tycho::TransactionContractChanges> = - HashMap::new(); + let mut transaction_contract_changes: HashMap<_, TransactionContractChanges> = HashMap::new(); // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to // convert into `TransactionContractChanges` @@ -176,7 +172,7 @@ pub fn map_changes( let tx = tx_component.tx.as_ref().unwrap(); transaction_contract_changes .entry(tx.index) - .or_insert_with(|| tycho::TransactionContractChanges::new(&tx)) + .or_insert_with(|| TransactionContractChanges::new(&tx)) .component_changes .extend_from_slice(&tx_component.components); }); @@ -185,12 +181,12 @@ pub fn map_changes( // `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store` this // block. Then, these balance changes are merged onto the existing map of tx contract changes, // inserting a new one if it doesn't exist. - balances::aggregate_balances_changes(balance_store, deltas) + aggregate_balances_changes(balance_store, deltas) .into_iter() .for_each(|(_, (tx, balances))| { transaction_contract_changes .entry(tx.index) - .or_insert_with(|| tycho::TransactionContractChanges::new(&tx)) + .or_insert_with(|| TransactionContractChanges::new(&tx)) .balance_changes .extend(balances.into_iter().map(|(_, change)| change)); }); @@ -208,7 +204,7 @@ pub fn map_changes( // Process all `transaction_contract_changes` for final output in the `BlockContractChanges`, // sorted by transaction index (the key). - Ok(tycho::BlockContractChanges { + Ok(BlockContractChanges { block: Some((&block).into()), changes: transaction_contract_changes .drain() diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index 2ef1bc8..16691c3 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -1,11 +1,9 @@ -use substreams_ethereum::pb::eth::v2::{Call, Log}; -use substreams_ethereum::{Event, Function}; - use crate::abi; use substreams::hex; -use tycho_substreams::pb::tycho::evm::v1::{ImplementationType, ProtocolComponent, Transaction}; - use substreams::scalar::BigInt; +use substreams_ethereum::pb::eth::v2::{Call, Log}; +use substreams_ethereum::{Event, Function}; +use tycho_substreams::prelude::*; /// This trait defines some helpers for serializing and deserializing `Vec Date: Wed, 13 Mar 2024 23:31:08 +0000 Subject: [PATCH 22/37] Move crates under substreams directory. This way we can run GHA jobs depending on what files changed. --- .github/workflows/{test.yml => evm.yml} | 7 +++++-- {crates => substreams/crates}/tycho-substreams/Cargo.lock | 0 {crates => substreams/crates}/tycho-substreams/Cargo.toml | 0 {crates => substreams/crates}/tycho-substreams/Readme.md | 4 ++-- .../crates}/tycho-substreams/buf.gen.yaml | 0 .../crates}/tycho-substreams/rustfmt.toml | 0 .../crates}/tycho-substreams/src/balances.rs | 0 .../crates}/tycho-substreams/src/contract.rs | 0 {crates => substreams/crates}/tycho-substreams/src/lib.rs | 0 .../crates}/tycho-substreams/src/mock_store.rs | 0 .../crates}/tycho-substreams/src/models.rs | 0 .../crates}/tycho-substreams/src/pb/mod.rs | 0 .../crates}/tycho-substreams/src/pb/tycho.evm.v1.rs | 0 substreams/ethereum-balancer/Cargo.toml | 2 +- 14 files changed, 8 insertions(+), 5 deletions(-) rename .github/workflows/{test.yml => evm.yml} (92%) rename {crates => substreams/crates}/tycho-substreams/Cargo.lock (100%) rename {crates => substreams/crates}/tycho-substreams/Cargo.toml (100%) rename {crates => substreams/crates}/tycho-substreams/Readme.md (75%) rename {crates => substreams/crates}/tycho-substreams/buf.gen.yaml (100%) rename {crates => substreams/crates}/tycho-substreams/rustfmt.toml (100%) rename {crates => substreams/crates}/tycho-substreams/src/balances.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/contract.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/lib.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/mock_store.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/models.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/pb/mod.rs (100%) rename {crates => substreams/crates}/tycho-substreams/src/pb/tycho.evm.v1.rs (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/evm.yml similarity index 92% rename from .github/workflows/test.yml rename to .github/workflows/evm.yml index c64c94f..c75f40d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/evm.yml @@ -1,6 +1,9 @@ -name: test +name: test evm -on: workflow_dispatch +on: + push: + paths: + - "evm/**" env: FOUNDRY_PROFILE: ci diff --git a/crates/tycho-substreams/Cargo.lock b/substreams/crates/tycho-substreams/Cargo.lock similarity index 100% rename from crates/tycho-substreams/Cargo.lock rename to substreams/crates/tycho-substreams/Cargo.lock diff --git a/crates/tycho-substreams/Cargo.toml b/substreams/crates/tycho-substreams/Cargo.toml similarity index 100% rename from crates/tycho-substreams/Cargo.toml rename to substreams/crates/tycho-substreams/Cargo.toml diff --git a/crates/tycho-substreams/Readme.md b/substreams/crates/tycho-substreams/Readme.md similarity index 75% rename from crates/tycho-substreams/Readme.md rename to substreams/crates/tycho-substreams/Readme.md index 56b374b..20f868b 100644 --- a/crates/tycho-substreams/Readme.md +++ b/substreams/crates/tycho-substreams/Readme.md @@ -13,6 +13,6 @@ directory: ```bash buf generate \ --path tycho \ - --template ../crates/tycho-substreams/buf.gen.yaml \ - --output ../crates/tycho-substreams/ + --template ../substreams/crates/tycho-substreams/buf.gen.yaml \ + --output ../substreams/crates/tycho-substreams/ ``` \ No newline at end of file diff --git a/crates/tycho-substreams/buf.gen.yaml b/substreams/crates/tycho-substreams/buf.gen.yaml similarity index 100% rename from crates/tycho-substreams/buf.gen.yaml rename to substreams/crates/tycho-substreams/buf.gen.yaml diff --git a/crates/tycho-substreams/rustfmt.toml b/substreams/crates/tycho-substreams/rustfmt.toml similarity index 100% rename from crates/tycho-substreams/rustfmt.toml rename to substreams/crates/tycho-substreams/rustfmt.toml diff --git a/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs similarity index 100% rename from crates/tycho-substreams/src/balances.rs rename to substreams/crates/tycho-substreams/src/balances.rs diff --git a/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs similarity index 100% rename from crates/tycho-substreams/src/contract.rs rename to substreams/crates/tycho-substreams/src/contract.rs diff --git a/crates/tycho-substreams/src/lib.rs b/substreams/crates/tycho-substreams/src/lib.rs similarity index 100% rename from crates/tycho-substreams/src/lib.rs rename to substreams/crates/tycho-substreams/src/lib.rs diff --git a/crates/tycho-substreams/src/mock_store.rs b/substreams/crates/tycho-substreams/src/mock_store.rs similarity index 100% rename from crates/tycho-substreams/src/mock_store.rs rename to substreams/crates/tycho-substreams/src/mock_store.rs diff --git a/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs similarity index 100% rename from crates/tycho-substreams/src/models.rs rename to substreams/crates/tycho-substreams/src/models.rs diff --git a/crates/tycho-substreams/src/pb/mod.rs b/substreams/crates/tycho-substreams/src/pb/mod.rs similarity index 100% rename from crates/tycho-substreams/src/pb/mod.rs rename to substreams/crates/tycho-substreams/src/pb/mod.rs diff --git a/crates/tycho-substreams/src/pb/tycho.evm.v1.rs b/substreams/crates/tycho-substreams/src/pb/tycho.evm.v1.rs similarity index 100% rename from crates/tycho-substreams/src/pb/tycho.evm.v1.rs rename to substreams/crates/tycho-substreams/src/pb/tycho.evm.v1.rs diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml index 0a964e5..16ddbdf 100644 --- a/substreams/ethereum-balancer/Cargo.toml +++ b/substreams/ethereum-balancer/Cargo.toml @@ -19,7 +19,7 @@ anyhow = "1.0.75" prost-types = "0.12.3" num-bigint = "0.4.4" itertools = "0.12.0" -tycho-substreams = {path ="../../crates/tycho-substreams"} +tycho-substreams = {path ="../crates/tycho-substreams"} [build-dependencies] anyhow = "1" From 425628ae97dbfb7391d22abfdf57d9763e197dfe Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 00:19:54 +0000 Subject: [PATCH 23/37] Create a workspace and make clippy happy. --- .../{crates/tycho-substreams => }/Cargo.lock | 195 ++- substreams/Cargo.toml | 22 + substreams/crates/tycho-substreams/Cargo.toml | 8 +- .../crates/tycho-substreams/src/balances.rs | 12 +- .../crates/tycho-substreams/src/contract.rs | 6 +- .../crates/tycho-substreams/src/mock_store.rs | 4 +- substreams/ethereum-balancer/Cargo.lock | 1281 ----------------- substreams/ethereum-balancer/Cargo.toml | 16 +- substreams/ethereum-balancer/src/modules.rs | 6 +- .../ethereum-balancer/src/pool_factories.rs | 14 +- .../tycho-substreams => }/rustfmt.toml | 3 +- 11 files changed, 222 insertions(+), 1345 deletions(-) rename substreams/{crates/tycho-substreams => }/Cargo.lock (87%) create mode 100644 substreams/Cargo.toml delete mode 100644 substreams/ethereum-balancer/Cargo.lock rename substreams/{crates/tycho-substreams => }/rustfmt.toml (91%) diff --git a/substreams/crates/tycho-substreams/Cargo.lock b/substreams/Cargo.lock similarity index 87% rename from substreams/crates/tycho-substreams/Cargo.lock rename to substreams/Cargo.lock index cd827d8..f5fe0e5 100644 --- a/substreams/crates/tycho-substreams/Cargo.lock +++ b/substreams/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayvec" @@ -154,7 +154,24 @@ version = "17.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" dependencies = [ - "ethereum-types", + "ethereum-types 0.13.1", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types 0.14.1", "hex", "once_cell", "regex", @@ -172,9 +189,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" dependencies = [ "crunchy", - "fixed-hash", + "fixed-hash 0.7.0", "impl-rlp", - "impl-serde", + "impl-serde 0.3.2", + "tiny-keccak", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash 0.8.0", + "impl-rlp", + "impl-serde 0.4.0", "tiny-keccak", ] @@ -184,11 +214,25 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" dependencies = [ - "ethbloom", - "fixed-hash", + "ethbloom 0.12.1", + "fixed-hash 0.7.0", "impl-rlp", - "impl-serde", - "primitive-types", + "impl-serde 0.3.2", + "primitive-types 0.11.1", + "uint", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom 0.13.0", + "fixed-hash 0.8.0", + "impl-rlp", + "impl-serde 0.4.0", + "primitive-types 0.12.2", "uint", ] @@ -210,6 +254,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -267,6 +323,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "home" version = "0.5.9" @@ -303,6 +365,15 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -495,10 +566,23 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ - "fixed-hash", + "fixed-hash 0.7.0", "impl-codec", "impl-rlp", - "impl-serde", + "impl-serde 0.3.2", + "uint", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", + "impl-codec", + "impl-rlp", + "impl-serde 0.4.0", "uint", ] @@ -514,9 +598,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -528,7 +612,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive 0.12.3", ] [[package]] @@ -545,8 +639,8 @@ dependencies = [ "multimap", "petgraph", "prettyplease", - "prost", - "prost-types", + "prost 0.11.9", + "prost-types 0.11.9", "regex", "syn 1.0.109", "tempfile", @@ -566,13 +660,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "prost-types" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ - "prost", + "prost 0.11.9", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", ] [[package]] @@ -740,14 +856,14 @@ dependencies = [ "anyhow", "bigdecimal", "hex", - "hex-literal", + "hex-literal 0.3.4", "num-bigint", "num-integer", "num-traits", "pad", - "prost", + "prost 0.11.9", "prost-build", - "prost-types", + "prost-types 0.11.9", "substreams-macro", "thiserror", ] @@ -773,7 +889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c04307913a355aaf2a1bb7186d4bc7e36875f3d4aff77b47e83f1b63b24da55" dependencies = [ "anyhow", - "ethabi", + "ethabi 17.2.0", "heck", "hex", "prettyplease", @@ -783,6 +899,25 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "substreams-ethereum-balancer" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "ethabi 18.0.0", + "getrandom", + "hex", + "hex-literal 0.4.1", + "itertools 0.12.1", + "num-bigint", + "prost 0.11.9", + "prost-types 0.12.3", + "substreams", + "substreams-ethereum", + "tycho-substreams", +] + [[package]] name = "substreams-ethereum-core" version = "0.9.9" @@ -790,12 +925,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db9048cc9a66873ab7069ef958c2684994e6ee323da49c186b19156fdb4ca131" dependencies = [ "bigdecimal", - "ethabi", + "ethabi 17.2.0", "getrandom", "num-bigint", - "prost", + "prost 0.11.9", "prost-build", - "prost-types", + "prost-types 0.11.9", "substreams", ] @@ -805,7 +940,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e862928bee8653f5c9291ac619c8dc0da14ca61d8cd8d89b3acdbbde4d0bf304" dependencies = [ - "ethabi", + "ethabi 17.2.0", "heck", "hex", "num-bigint", @@ -869,18 +1004,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", @@ -919,7 +1054,7 @@ version = "0.1.0" dependencies = [ "hex", "itertools 0.12.1", - "prost", + "prost 0.11.9", "substreams", "substreams-ethereum", ] diff --git a/substreams/Cargo.toml b/substreams/Cargo.toml new file mode 100644 index 0000000..8bcd85d --- /dev/null +++ b/substreams/Cargo.toml @@ -0,0 +1,22 @@ +[workspace] +members = [ + "ethereum-balancer", + "crates/tycho-substreams", +] +resolver = "2" + + +[workspace.dependencies] +substreams-ethereum = "0.9.9" +substreams = "0.5" +prost = "0.11" +prost-types = "0.12.3" +hex-literal = "0.4.1" +hex = "0.4.3" +ethabi = "18.0.0" +tycho-substreams = {path ="crates/tycho-substreams"} + +[profile.release] +lto = true +opt-level = 's' +strip = "debuginfo" \ No newline at end of file diff --git a/substreams/crates/tycho-substreams/Cargo.toml b/substreams/crates/tycho-substreams/Cargo.toml index cc0f7bc..3908f81 100644 --- a/substreams/crates/tycho-substreams/Cargo.toml +++ b/substreams/crates/tycho-substreams/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -substreams-ethereum = "0.9.9" -substreams = "0.5" -prost = "0.11" -hex = "0.4.3" +substreams-ethereum.workspace = true +substreams.workspace = true +prost.workspace = true +hex.workspace = true itertools = "0.12.0" \ No newline at end of file diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs index 8046fe1..74a38fa 100644 --- a/substreams/crates/tycho-substreams/src/balances.rs +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -63,6 +63,8 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd, (Transaction, HashMap, BalanceChange>)>; + /// Aggregates absolute balances per transaction and token. /// /// ## Arguments @@ -82,7 +84,7 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd HashMap, (Transaction, HashMap, BalanceChange>)> { +) -> TxAggregatedBalances { balance_store .deltas .into_iter() @@ -207,9 +209,9 @@ mod tests { let token_1 = hex::decode("babe00").unwrap(); let t0_key = - format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(&token_0)); + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(token_0)); let t1_key = - format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(&token_1)); + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(token_1)); StoreDeltas { deltas: vec![ StoreDelta { @@ -283,12 +285,12 @@ mod tests { let res_0 = store.get_last(format!( "{}:{}", String::from_utf8(comp_id.clone()).unwrap(), - hex::encode(&token_0) + hex::encode(token_0) )); let res_1 = store.get_last(format!( "{}:{}", String::from_utf8(comp_id.clone()).unwrap(), - hex::encode(&token_1) + hex::encode(token_1) )); assert_eq!(res_0, Some(BigInt::from_str("+999").unwrap())); diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs index f054380..e02ba2e 100644 --- a/substreams/crates/tycho-substreams/src/contract.rs +++ b/substreams/crates/tycho-substreams/src/contract.rs @@ -49,11 +49,7 @@ impl InterimContractChange { balance: vec![], code: vec![], slots: Default::default(), - change: if creation { - tycho::ChangeType::Creation.into() - } else { - tycho::ChangeType::Update.into() - }, + change: if creation { tycho::ChangeType::Creation } else { tycho::ChangeType::Update }, } } } diff --git a/substreams/crates/tycho-substreams/src/mock_store.rs b/substreams/crates/tycho-substreams/src/mock_store.rs index a1c0cd2..6c1349f 100644 --- a/substreams/crates/tycho-substreams/src/mock_store.rs +++ b/substreams/crates/tycho-substreams/src/mock_store.rs @@ -7,9 +7,11 @@ use std::rc::Rc; use substreams::prelude::{BigInt, StoreDelete, StoreGet, StoreNew}; use substreams::store::StoreAdd; +type BigIntStore = HashMap>; + #[derive(Debug, Clone)] pub struct MockStore { - data: Rc>>>, + data: Rc>, } impl StoreDelete for MockStore { diff --git a/substreams/ethereum-balancer/Cargo.lock b/substreams/ethereum-balancer/Cargo.lock deleted file mode 100644 index e2d81a0..0000000 --- a/substreams/ethereum-balancer/Cargo.lock +++ /dev/null @@ -1,1281 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bigdecimal" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "ethabi" -version = "17.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" -dependencies = [ - "ethereum-types 0.13.1", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types 0.14.1", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" -dependencies = [ - "crunchy", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde 0.3.2", - "tiny-keccak", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash 0.8.0", - "impl-rlp", - "impl-serde 0.4.0", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" -dependencies = [ - "ethbloom 0.12.1", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde 0.3.2", - "primitive-types 0.11.1", - "uint", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom 0.13.0", - "fixed-hash 0.8.0", - "impl-rlp", - "impl-serde 0.4.0", - "primitive-types 0.12.2", - "uint", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" - -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "pad" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "primitive-types" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" -dependencies = [ - "fixed-hash 0.7.0", - "impl-codec", - "impl-rlp", - "impl-serde 0.3.2", - "uint", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash 0.8.0", - "impl-codec", - "impl-rlp", - "impl-serde 0.4.0", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" -dependencies = [ - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive 0.12.3", -] - -[[package]] -name = "prost-build" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" -dependencies = [ - "bytes", - "heck", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 2.0.41", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost 0.12.3", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustix" -version = "0.38.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.41", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "substreams" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3524a4e2931ff6cd58783e62adbd7e44f461752eca0c423793cfb462351f24" -dependencies = [ - "anyhow", - "bigdecimal", - "hex", - "hex-literal 0.3.4", - "num-bigint", - "num-integer", - "num-traits", - "pad", - "prost 0.11.9", - "prost-build", - "prost-types 0.11.9", - "substreams-macro", - "thiserror", -] - -[[package]] -name = "substreams-ethereum" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f45dc04be50b7ca08d6d5c4560ee3eeba16ccaa1c124d0361bb30b5b84e28b" -dependencies = [ - "getrandom", - "num-bigint", - "substreams", - "substreams-ethereum-abigen", - "substreams-ethereum-core", - "substreams-ethereum-derive", -] - -[[package]] -name = "substreams-ethereum-abigen" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c04307913a355aaf2a1bb7186d4bc7e36875f3d4aff77b47e83f1b63b24da55" -dependencies = [ - "anyhow", - "ethabi 17.2.0", - "heck", - "hex", - "prettyplease", - "proc-macro2", - "quote", - "substreams-ethereum-core", - "syn 1.0.109", -] - -[[package]] -name = "substreams-ethereum-balancer" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytes", - "ethabi 18.0.0", - "getrandom", - "hex", - "hex-literal 0.4.1", - "itertools 0.12.0", - "num-bigint", - "prost 0.11.9", - "prost-types 0.12.3", - "substreams", - "substreams-ethereum", - "tycho-substreams", -] - -[[package]] -name = "substreams-ethereum-core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db9048cc9a66873ab7069ef958c2684994e6ee323da49c186b19156fdb4ca131" -dependencies = [ - "bigdecimal", - "ethabi 17.2.0", - "getrandom", - "num-bigint", - "prost 0.11.9", - "prost-build", - "prost-types 0.11.9", - "substreams", -] - -[[package]] -name = "substreams-ethereum-derive" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e862928bee8653f5c9291ac619c8dc0da14ca61d8cd8d89b3acdbbde4d0bf304" -dependencies = [ - "ethabi 17.2.0", - "heck", - "hex", - "num-bigint", - "proc-macro2", - "quote", - "substreams-ethereum-abigen", - "syn 1.0.109", -] - -[[package]] -name = "substreams-macro" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c2b15adf5b4d7a6d1a73c73df951a6b2df6fbb4f0b41304dc28c5550ce0ed0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "thiserror" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.41", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" - -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tycho-substreams" -version = "0.1.0" -dependencies = [ - "hex", - "itertools 0.12.0", - "prost 0.11.9", - "substreams", - "substreams-ethereum", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winnow" -version = "0.5.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" -dependencies = [ - "memchr", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml index 16ddbdf..885ab93 100644 --- a/substreams/ethereum-balancer/Cargo.toml +++ b/substreams/ethereum-balancer/Cargo.toml @@ -8,18 +8,18 @@ name = "substreams_ethereum_balancer" crate-type = ["cdylib"] [dependencies] -substreams = "0.5" -substreams-ethereum = "0.9.9" -prost = "0.11" -hex-literal = "0.4.1" -ethabi = "18.0.0" -hex = "0.4.2" +substreams.workspace = true +substreams-ethereum.workspace = true +prost.workspace = true +prost-types.workspace = true +hex-literal.workspace = true +ethabi.workspace = true +hex.workspace = true bytes = "1.5.0" anyhow = "1.0.75" -prost-types = "0.12.3" num-bigint = "0.4.4" itertools = "0.12.0" -tycho-substreams = {path ="../crates/tycho-substreams"} +tycho-substreams.workspace = true [build-dependencies] anyhow = "1" diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index 728a53e..d5bf495 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -172,7 +172,7 @@ pub fn map_changes( let tx = tx_component.tx.as_ref().unwrap(); transaction_contract_changes .entry(tx.index) - .or_insert_with(|| TransactionContractChanges::new(&tx)) + .or_insert_with(|| TransactionContractChanges::new(tx)) .component_changes .extend_from_slice(&tx_component.components); }); @@ -188,7 +188,7 @@ pub fn map_changes( .entry(tx.index) .or_insert_with(|| TransactionContractChanges::new(&tx)) .balance_changes - .extend(balances.into_iter().map(|(_, change)| change)); + .extend(balances.into_values()); }); // Extract and insert any storage changes that happened for any of the components. @@ -196,7 +196,7 @@ pub fn map_changes( &block, |addr| { components_store - .get_last(format!("pool:{0}", hex::encode(&addr))) + .get_last(format!("pool:{0}", hex::encode(addr))) .is_some() }, &mut transaction_contract_changes, diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index 16691c3..d2cfc2f 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -53,7 +53,7 @@ pub fn address_map( abi::weighted_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&create_call.tokens) .with_attributes(&[ ("pool_type", "WeightedPoolFactory".as_bytes()), @@ -72,7 +72,7 @@ pub fn address_map( abi::composable_stable_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&create_call.tokens) .with_attributes(&[("pool_type", "ComposableStablePoolFactory".as_bytes())]) .as_swap_type("balancer_pool", ImplementationType::Vm), @@ -85,7 +85,7 @@ pub fn address_map( abi::erc_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&[create_call.main_token, create_call.wrapped_token]) .with_attributes(&[ ("pool_type", "ERC4626LinearPoolFactory".as_bytes()), @@ -104,7 +104,7 @@ pub fn address_map( abi::euler_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&[create_call.main_token, create_call.wrapped_token]) .with_attributes(&[ ("pool_type", "EulerLinearPoolFactory".as_bytes()), @@ -170,7 +170,7 @@ pub fn address_map( abi::silo_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&[create_call.main_token, create_call.wrapped_token]) .with_attributes(&[ ("pool_type", "SiloLinearPoolFactory".as_bytes()), @@ -189,7 +189,7 @@ pub fn address_map( abi::yearn_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&[create_call.main_token, create_call.wrapped_token]) .with_attributes(&[ ("pool_type", "YearnLinearPoolFactory".as_bytes()), @@ -210,7 +210,7 @@ pub fn address_map( abi::weighted_pool_tokens_factory::events::PoolCreated::match_and_decode(log)?; Some( - ProtocolComponent::at_contract(&pool_created.pool, &tx) + ProtocolComponent::at_contract(&pool_created.pool, tx) .with_tokens(&create_call.tokens) .with_attributes(&[ ("pool_type", "WeightedPool2TokensFactory".as_bytes()), diff --git a/substreams/crates/tycho-substreams/rustfmt.toml b/substreams/rustfmt.toml similarity index 91% rename from substreams/crates/tycho-substreams/rustfmt.toml rename to substreams/rustfmt.toml index d0c0193..ce9e1ec 100644 --- a/substreams/crates/tycho-substreams/rustfmt.toml +++ b/substreams/rustfmt.toml @@ -9,5 +9,6 @@ trailing_semicolon = false use_field_init_shorthand = true chain_width = 40 ignore = [ - "src/pb", + "*/pb", + "*/abi", ] \ No newline at end of file From 6b6e42e2f8697c4f65de0122844a799309ad3f5e Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 00:27:52 +0000 Subject: [PATCH 24/37] Run rustfmt --- .../crates/tycho-substreams/src/balances.rs | 47 +++++++------- .../crates/tycho-substreams/src/contract.rs | 16 ++--- .../crates/tycho-substreams/src/mock_store.rs | 10 +-- substreams/ethereum-balancer/src/modules.rs | 62 ++++++++----------- .../ethereum-balancer/src/pool_factories.rs | 36 +++++++---- substreams/rustfmt.toml | 4 +- 6 files changed, 92 insertions(+), 83 deletions(-) diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs index 74a38fa..85e1311 100644 --- a/substreams/crates/tycho-substreams/src/balances.rs +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -3,21 +3,21 @@ //! //! To aggregate relative balances changes to absolute balances the general approach is: //! -//! 1. Use a map function that will extract a `BlockBalanceDeltas` message. BalanceDeltas -//! within this message are required to have increasing ordinals so that -//! the order of relative balance changes is unambiguous. -//! 2. Store the balances changes with a store handler. You can use the -//! `store_balance_changes` library method directly for this. -//! 3. In the output module, use aggregate_balance_changes to receive an -//! aggregated map of absolute balances. -//! +//! 1. Use a map function that will extract a `BlockBalanceDeltas` message. BalanceDeltas within +//! this message are required to have increasing ordinals so that the order of relative balance +//! changes is unambiguous. +//! 2. Store the balances changes with a store handler. You can use the `store_balance_changes` +//! library method directly for this. +//! 3. In the output module, use aggregate_balance_changes to receive an aggregated map of absolute +//! balances. use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}; use itertools::Itertools; -use std::collections::HashMap; -use std::str::FromStr; -use substreams::key; -use substreams::pb::substreams::StoreDeltas; -use substreams::prelude::{BigInt, StoreAdd}; +use std::{collections::HashMap, str::FromStr}; +use substreams::{ + key, + pb::substreams::StoreDeltas, + prelude::{BigInt, StoreAdd}, +}; /// Store relative balances changes in a additive manner. /// @@ -25,9 +25,9 @@ use substreams::prelude::{BigInt, StoreAdd}; /// /// ## Arguments /// -/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. -/// Note: relative balance deltas must have strictly increasing ordinals per token -/// address, will panic otherwise. +/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. Note: +/// relative balance deltas must have strictly increasing ordinals per token address, will panic +/// otherwise. /// * `store` - An AddStore that will add relative balance changes. /// /// This method is meant to be used in combination with `aggregate_balances_changes` @@ -68,8 +68,7 @@ type TxAggregatedBalances = HashMap, (Transaction, HashMap, Bala /// Aggregates absolute balances per transaction and token. /// /// ## Arguments -/// * `balance_store` - A `StoreDeltas` with all changes that occured in the source -/// store module. +/// * `balance_store` - A `StoreDeltas` with all changes that occured in the source store module. /// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. /// /// Reads absolute balance values from the additive store (see `store_balance_changes` @@ -127,10 +126,14 @@ pub fn aggregate_balances_changes( #[cfg(test)] mod tests { use super::*; - use crate::mock_store::MockStore; - use crate::pb::tycho::evm::v1::{BalanceDelta, Transaction}; - use substreams::pb::substreams::StoreDelta; - use substreams::prelude::{StoreGet, StoreNew}; + use crate::{ + mock_store::MockStore, + pb::tycho::evm::v1::{BalanceDelta, Transaction}, + }; + use substreams::{ + pb::substreams::StoreDelta, + prelude::{StoreGet, StoreNew}, + }; fn block_balance_deltas() -> BlockBalanceDeltas { let comp_id = "0x42c0ffee" diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs index e02ba2e..a99fd60 100644 --- a/substreams/crates/tycho-substreams/src/contract.rs +++ b/substreams/crates/tycho-substreams/src/contract.rs @@ -10,9 +10,10 @@ /// more [here](https://streamingfastio.medium.com/new-block-model-to-accelerate-chain-integration-9f65126e5425) use std::collections::HashMap; -use substreams_ethereum::pb::eth; -use substreams_ethereum::pb::eth::v2::block::DetailLevel; -use substreams_ethereum::pb::eth::v2::StorageChange; +use substreams_ethereum::pb::{ + eth, + eth::v2::{block::DetailLevel, StorageChange}, +}; use crate::pb::tycho::evm::v1::{self as tycho}; @@ -78,7 +79,8 @@ impl From for tycho::ContractChange { /// ## Arguments /// /// * `block` - The block to extract changes from. Must be the extended block model. -/// * `inclusion_predicate` - A predicate function that determines if a contract address is relevant. +/// * `inclusion_predicate` - A predicate function that determines if a contract address is +/// relevant. /// * `transaction_contract_changes` - A mutable map to store the contract changes in. /// /// ## Panics @@ -189,9 +191,9 @@ pub fn extract_contract_changes bool>( .extend_from_slice(&code_change.new_code); }); - if !storage_changes.is_empty() - || !balance_changes.is_empty() - || !code_changes.is_empty() + if !storage_changes.is_empty() || + !balance_changes.is_empty() || + !code_changes.is_empty() { transaction_contract_changes .entry(block_tx.index.into()) diff --git a/substreams/crates/tycho-substreams/src/mock_store.rs b/substreams/crates/tycho-substreams/src/mock_store.rs index 6c1349f..70b252b 100644 --- a/substreams/crates/tycho-substreams/src/mock_store.rs +++ b/substreams/crates/tycho-substreams/src/mock_store.rs @@ -1,11 +1,11 @@ //! Contains a mock store for internal testing. //! //! Might make this public alter to users can test their store handlers. -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; -use substreams::prelude::{BigInt, StoreDelete, StoreGet, StoreNew}; -use substreams::store::StoreAdd; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use substreams::{ + prelude::{BigInt, StoreDelete, StoreGet, StoreNew}, + store::StoreAdd, +}; type BigIntStore = HashMap>; diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index d5bf495..b1747b1 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -2,16 +2,15 @@ use crate::{abi, pool_factories}; use anyhow::Result; use itertools::Itertools; use std::collections::HashMap; -use substreams::hex; -use substreams::pb::substreams::StoreDeltas; -use substreams::store::{ - StoreAdd, StoreAddBigInt, StoreAddInt64, StoreGet, StoreGetInt64, StoreNew, +use substreams::{ + hex, + pb::substreams::StoreDeltas, + store::{StoreAdd, StoreAddBigInt, StoreAddInt64, StoreGet, StoreGetInt64, StoreNew}, +}; +use substreams_ethereum::{pb::eth, Event}; +use tycho_substreams::{ + balances::aggregate_balances_changes, contract::extract_contract_changes, prelude::*, }; -use substreams_ethereum::pb::eth; -use substreams_ethereum::Event; -use tycho_substreams::balances::aggregate_balances_changes; -use tycho_substreams::contract::extract_contract_changes; -use tycho_substreams::prelude::*; const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); @@ -37,10 +36,7 @@ pub fn map_pools_created(block: eth::v2::Block) -> Result>(); if !components.is_empty() { - Some(TransactionProtocolComponents { - tx: Some(tx.into()), - components, - }) + Some(TransactionProtocolComponents { tx: Some(tx.into()), components }) } else { None } @@ -63,8 +59,8 @@ pub fn store_pools_created(map: BlockTransactionProtocolComponents, store: Store ); } -/// Since the `PoolBalanceChanged` and `Swap` 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. +/// Since the `PoolBalanceChanged` and `Swap` 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] pub fn map_balance_deltas( block: eth::v2::Block, @@ -79,12 +75,10 @@ pub fn map_balance_deltas( if let Some(ev) = abi::vault::events::PoolBalanceChanged::match_and_decode(vault_log.log) { - let component_id = format!( - "0x{}", - String::from_utf8(ev.pool_id[..20].to_vec()).unwrap() - ) - .as_bytes() - .to_vec(); + let component_id = + format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) + .as_bytes() + .to_vec(); if store .get_last(format!("pool:{}", hex::encode(&component_id))) @@ -101,12 +95,10 @@ pub fn map_balance_deltas( } } } else if let Some(ev) = abi::vault::events::Swap::match_and_decode(vault_log.log) { - let component_id = format!( - "0x{}", - String::from_utf8(ev.pool_id[..20].to_vec()).unwrap() - ) - .as_bytes() - .to_vec(); + let component_id = + format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) + .as_bytes() + .to_vec(); if store .get_last(format!("pool:{}", hex::encode(&component_id))) @@ -149,8 +141,8 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) /// Every contract change is grouped by transaction index via the `transaction_contract_changes` /// map. Each block of code will extend the `TransactionContractChanges` struct with the /// cooresponding changes (balance, component, contract), inserting a new one if it doesn't exist. -/// At the very end, the map can easily be sorted by index to ensure the final `BlockContractChanges` -/// is ordered by transactions properly. +/// At the very end, the map can easily be sorted by index to ensure the final +/// `BlockContractChanges` is ordered by transactions properly. #[substreams::handlers::map] pub fn map_changes( block: eth::v2::Block, @@ -178,9 +170,9 @@ pub fn map_changes( }); // Balance changes are gathered by the `StoreDelta` based on `PoolBalanceChanged` creating - // `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store` this - // block. Then, these balance changes are merged onto the existing map of tx contract changes, - // inserting a new one if it doesn't exist. + // `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store` + // this block. Then, these balance changes are merged onto the existing map of tx contract + // changes, inserting a new one if it doesn't exist. aggregate_balances_changes(balance_store, deltas) .into_iter() .for_each(|(_, (tx, balances))| { @@ -210,9 +202,9 @@ pub fn map_changes( .drain() .sorted_unstable_by_key(|(index, _)| *index) .filter_map(|(_, change)| { - if change.contract_changes.is_empty() - && change.component_changes.is_empty() - && change.balance_changes.is_empty() + if change.contract_changes.is_empty() && + change.component_changes.is_empty() && + change.balance_changes.is_empty() { None } else { diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs index d2cfc2f..5c2cd59 100644 --- a/substreams/ethereum-balancer/src/pool_factories.rs +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -1,8 +1,9 @@ use crate::abi; -use substreams::hex; -use substreams::scalar::BigInt; -use substreams_ethereum::pb::eth::v2::{Call, Log}; -use substreams_ethereum::{Event, Function}; +use substreams::{hex, scalar::BigInt}; +use substreams_ethereum::{ + pb::eth::v2::{Call, Log}, + Event, Function, +}; use tycho_substreams::prelude::*; /// This trait defines some helpers for serializing and deserializing `Vec { - // let create_call = abi::managed_pool_factory::functions::Create::match_and_decode(call)?; + // let create_call = + // abi::managed_pool_factory::functions::Create::match_and_decode(call)?; // let pool_created = // abi::managed_pool_factory::events::PoolCreated::match_and_decode(log)?; @@ -176,7 +184,9 @@ pub fn address_map( ("pool_type", "SiloLinearPoolFactory".as_bytes()), ( "upper_target", - &create_call.upper_target.to_signed_bytes_be(), + &create_call + .upper_target + .to_signed_bytes_be(), ), ]) .as_swap_type("balancer_pool", ImplementationType::Vm), @@ -195,7 +205,9 @@ pub fn address_map( ("pool_type", "YearnLinearPoolFactory".as_bytes()), ( "upper_target", - &create_call.upper_target.to_signed_bytes_be(), + &create_call + .upper_target + .to_signed_bytes_be(), ), ]) .as_swap_type("balancer_pool", ImplementationType::Vm), diff --git a/substreams/rustfmt.toml b/substreams/rustfmt.toml index ce9e1ec..1f27a7b 100644 --- a/substreams/rustfmt.toml +++ b/substreams/rustfmt.toml @@ -9,6 +9,6 @@ trailing_semicolon = false use_field_init_shorthand = true chain_width = 40 ignore = [ - "*/pb", - "*/abi", + "crates/tycho-substreams/src/pb", + "ethereum-balancer/src/abi", ] \ No newline at end of file From 981a0917278f84b4db886c115c0f0aae06d45918 Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 01:21:06 +0000 Subject: [PATCH 25/37] Add check and release scripts. Had to slightly adjust package names to make this work. --- substreams/Cargo.lock | 38 ++++++------- substreams/check.sh | 6 ++ substreams/ethereum-balancer/Cargo.toml | 4 +- substreams/ethereum-balancer/substreams.yaml | 12 +--- substreams/release.sh | 60 ++++++++++++++++++++ 5 files changed, 89 insertions(+), 31 deletions(-) create mode 100755 substreams/check.sh create mode 100755 substreams/release.sh diff --git a/substreams/Cargo.lock b/substreams/Cargo.lock index f5fe0e5..f89bb92 100644 --- a/substreams/Cargo.lock +++ b/substreams/Cargo.lock @@ -208,6 +208,25 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "ethereum-balancer" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "ethabi 18.0.0", + "getrandom", + "hex", + "hex-literal 0.4.1", + "itertools 0.12.1", + "num-bigint", + "prost 0.11.9", + "prost-types 0.12.3", + "substreams", + "substreams-ethereum", + "tycho-substreams", +] + [[package]] name = "ethereum-types" version = "0.13.1" @@ -899,25 +918,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "substreams-ethereum-balancer" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytes", - "ethabi 18.0.0", - "getrandom", - "hex", - "hex-literal 0.4.1", - "itertools 0.12.1", - "num-bigint", - "prost 0.11.9", - "prost-types 0.12.3", - "substreams", - "substreams-ethereum", - "tycho-substreams", -] - [[package]] name = "substreams-ethereum-core" version = "0.9.9" diff --git a/substreams/check.sh b/substreams/check.sh new file mode 100755 index 0000000..1821d18 --- /dev/null +++ b/substreams/check.sh @@ -0,0 +1,6 @@ +set -e + +cargo +nightly fmt -- --check +cargo +nightly clippy --all --all-features --all-targets -- -D warnings +cargo build --target wasm32-unknown-unknown --all-targets --all-features +cargo test --workspace --all-targets --all-features diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml index 885ab93..2aca957 100644 --- a/substreams/ethereum-balancer/Cargo.toml +++ b/substreams/ethereum-balancer/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "substreams-ethereum-balancer" +name = "ethereum-balancer" version = "0.1.0" edition = "2021" [lib] -name = "substreams_ethereum_balancer" +name = "ethereum_balancer" crate-type = ["cdylib"] [dependencies] diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 66da244..06f2ee7 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -1,20 +1,12 @@ specVersion: v0.1.0 package: - name: "substreams_ethereum_balancer" + name: "ethereum_balancer" version: v0.1.0 -protobuf: - files: - - tycho/evm/v1/vm.proto - - tycho/evm/v1/common.proto - - tycho/evm/v1/utils.proto - importPaths: - - ../../proto - binaries: default: type: wasm/rust-v1 - file: target/wasm32-unknown-unknown/release/substreams_ethereum_balancer.wasm + file: ../target/wasm32-unknown-unknown/release/ethereum_balancer.wasm modules: - name: map_pools_created diff --git a/substreams/release.sh b/substreams/release.sh new file mode 100755 index 0000000..27b50e6 --- /dev/null +++ b/substreams/release.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Allows releasing multiple substream packages within the same repo. +# To trigger a release simply create a tag with [package-name]-[semver]. +# The script will look for these tags, then infer which package needs to be built and +# released. + +# Try to get the tag name associated with the current HEAD commit +current_tag=$(git describe --tags --exact-match HEAD 2>/dev/null) + +if [ -n "$current_tag" ]; then + # If the HEAD is at a tag, extract the prefix and version + if [[ $current_tag =~ ^([a-zA-Z-]*-)?([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + # Prefix without the trailing hyphen (if any) + package="${BASH_REMATCH[1]%?}" + # Semantic version + version="${BASH_REMATCH[2]}" + tag=$current_tag + + cargo_version=$(cargo pkgid -p ethereum-balancer | cut -d# -f2 | cut -d: -f2) + if [[ "$cargo_version" != "$version" ]]; then + echo "Error: Cargo version: ${cargo_version} does not match tag version: ${version}!" + exit 1 + fi + # Check if the Git repository is dirty + if [ -n "$(git status --porcelain)" ]; then + echo "Error: The repository is dirty. Please commit or stash your changes." + exit 1 + fi + else + echo "Error: Current tag ($current_tag) does not match the expected format." + exit 1 + fi +else + # If the HEAD is not at a tag, construct the tag name with the pre-release postfix + if [ -z "$1" ]; then + echo "Error: package argument is required to create a pre release!" + exit 1 + fi + package=$1 + + version_prefix=$(git describe --tags --match "$package-*" --abbrev=0 2>/dev/null) + if [ -z "$version_prefix" ]; then + # If no tags are found in the history, default to version 0.0.1 + version_prefix="0.0.1" + fi + + # Get the short commit hash of the current HEAD + commit_hash=$(git rev-parse --short HEAD) + version="${version_prefix}-pre.${commit_hash}" + # Combine version prefix with commit hash + tag="${package}-${version}" +fi + +cargo build --target wasm32-unknown-unknown --release -p "$package" +mkdir -p ./target/spkg/ +substreams pack $package/substreams.yaml -o ./target/spkg/$package-$version.spkg +aws s3 cp ./target/spkg/$package-$version.spkg "s3://repository.propeller/substreams/$package/$version.spkg" + +echo "Released substreams package: "s3://repository.propeller/substreams/$package/$version.spkg"" \ No newline at end of file From b0fe5bc4e11df0a14dbe1f082fc190e50679c097 Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 01:35:21 +0000 Subject: [PATCH 26/37] Add github CI for substreams --- .github/workflows/substream.ci.yaml | 59 +++++++++++++++++++ .../crates/tycho-substreams/src/balances.rs | 5 +- 2 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/substream.ci.yaml diff --git a/.github/workflows/substream.ci.yaml b/.github/workflows/substream.ci.yaml new file mode 100644 index 0000000..32c2aee --- /dev/null +++ b/.github/workflows/substream.ci.yaml @@ -0,0 +1,59 @@ +name: Substreams CI + +on: + push: + paths: + - "substreams/**" + +jobs: + lint: + name: Substreams Lint + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: nightly + components: clippy, rustfmt + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run checks + run: | + cd substreams + cargo +nightly fmt -- --check + cargo +nightly clippy --all --all-features --all-targets -- -D warnings + + test: + name: Substreams Test + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: stable + targets: wasm32-unknown-unknown + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run checks + run: | + cd substreams + cargo build --target wasm32-unknown-unknown --all-targets --all-features + cargo test --workspace --all-targets --all-features diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs index 85e1311..862e1a2 100644 --- a/substreams/crates/tycho-substreams/src/balances.rs +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -126,10 +126,7 @@ pub fn aggregate_balances_changes( #[cfg(test)] mod tests { use super::*; - use crate::{ - mock_store::MockStore, - pb::tycho::evm::v1::{BalanceDelta, Transaction}, - }; + use crate::{mock_store::MockStore, pb::tycho::evm::v1::BalanceDelta}; use substreams::{ pb::substreams::StoreDelta, prelude::{StoreGet, StoreNew}, From 2288e12032441f930690d397cce43e716c393cab Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 01:42:28 +0000 Subject: [PATCH 27/37] Implement a substreams CD --- .github/workflows/substream.cd.yaml | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/substream.cd.yaml diff --git a/.github/workflows/substream.cd.yaml b/.github/workflows/substream.cd.yaml new file mode 100644 index 0000000..307c4de --- /dev/null +++ b/.github/workflows/substream.cd.yaml @@ -0,0 +1,37 @@ +name: Substreams CD + +on: + push: + tags: + - "ethereum-*" + workflow_dispatch: + inputs: + package: + required: true + description: "Package to build" + +jobs: + Release: + name: Release ${{ inputs.package }} + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: stable + targets: wasm32-unknown-unknown + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run checks + run: | + cd substreams + ./release.sh ${{ inputs.package }} From f88fb952b0e4c1f08c5957c8a2966d37ae521ecc Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 02:10:53 +0000 Subject: [PATCH 28/37] Add substreams cli installation. Comment out S3 upload for now. --- .github/workflows/substream.cd.yaml | 8 ++++++++ substreams/release.sh | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/substream.cd.yaml b/.github/workflows/substream.cd.yaml index 307c4de..8e99d96 100644 --- a/.github/workflows/substream.cd.yaml +++ b/.github/workflows/substream.cd.yaml @@ -31,6 +31,14 @@ jobs: with: cache-on-failure: true + - name: Install Substreams CLI + run: | + # Use correct binary for your platform + LINK=$(curl -s https://api.github.com/repos/streamingfast/substreams/releases/latest | awk "/download.url.*linux_$(uname -m)/ {print \$2}" | sed 's/"//g') + curl -L "$LINK" | tar zxf - -C /usr/local/bin + chmod +x /usr/local/bin/substreams + substreams --version + - name: Run checks run: | cd substreams diff --git a/substreams/release.sh b/substreams/release.sh index 27b50e6..d6dc840 100755 --- a/substreams/release.sh +++ b/substreams/release.sh @@ -55,6 +55,6 @@ fi cargo build --target wasm32-unknown-unknown --release -p "$package" mkdir -p ./target/spkg/ substreams pack $package/substreams.yaml -o ./target/spkg/$package-$version.spkg -aws s3 cp ./target/spkg/$package-$version.spkg "s3://repository.propeller/substreams/$package/$version.spkg" +# aws s3 cp ./target/spkg/$package-$version.spkg "s3://repository.propeller/substreams/$package/$version.spkg" echo "Released substreams package: "s3://repository.propeller/substreams/$package/$version.spkg"" \ No newline at end of file From 3f5a74260d49aa45be93636879419e91335b5a89 Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 09:30:16 +0000 Subject: [PATCH 29/37] Adjust and uncomment s3 path. --- substreams/release.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/substreams/release.sh b/substreams/release.sh index d6dc840..e011e95 100755 --- a/substreams/release.sh +++ b/substreams/release.sh @@ -15,7 +15,6 @@ if [ -n "$current_tag" ]; then package="${BASH_REMATCH[1]%?}" # Semantic version version="${BASH_REMATCH[2]}" - tag=$current_tag cargo_version=$(cargo pkgid -p ethereum-balancer | cut -d# -f2 | cut -d: -f2) if [[ "$cargo_version" != "$version" ]]; then @@ -48,13 +47,14 @@ else # Get the short commit hash of the current HEAD commit_hash=$(git rev-parse --short HEAD) version="${version_prefix}-pre.${commit_hash}" - # Combine version prefix with commit hash - tag="${package}-${version}" fi +REPOSITORY=${REPOSITORY:-"s3://repo.propellerheads/substreams"} +repository_path="$REPOSITORY/$package/$package-$version.spkg" + cargo build --target wasm32-unknown-unknown --release -p "$package" mkdir -p ./target/spkg/ substreams pack $package/substreams.yaml -o ./target/spkg/$package-$version.spkg -# aws s3 cp ./target/spkg/$package-$version.spkg "s3://repository.propeller/substreams/$package/$version.spkg" +aws s3 cp ./target/spkg/$package-$version.spkg $repository_path -echo "Released substreams package: "s3://repository.propeller/substreams/$package/$version.spkg"" \ No newline at end of file +echo "Released substreams package: '$repository_path'" \ No newline at end of file From e70d5f0e86320abf9def12ffa5da14ed31aab884 Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 11:04:41 +0000 Subject: [PATCH 30/37] Clip balances at 0. In case we get negative balances, which happens sometimes e.g. in balancer and seems to be due to some rounding issues within the protocol, we simply clip the balance at 0 so we never emit negative balances as tycho-indexer the upstream system will interpret the balance bytes as unsigned integers. --- .../crates/tycho-substreams/src/balances.rs | 85 +++++++++++++------ .../crates/tycho-substreams/src/contract.rs | 30 +++++-- .../crates/tycho-substreams/src/models.rs | 58 +++++++++---- 3 files changed, 122 insertions(+), 51 deletions(-) diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs index 862e1a2..707f60d 100644 --- a/substreams/crates/tycho-substreams/src/balances.rs +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -1,15 +1,26 @@ -//! Utilities to handle relative balances. +//! Module for Handling Relative Balance Changes. //! +//! This module facilitates the conversion of relative balance changes into absolute balances, +//! employing a structured approach to ensure the accurate representation of balance data. //! -//! To aggregate relative balances changes to absolute balances the general approach is: +//! Process Overview: //! -//! 1. Use a map function that will extract a `BlockBalanceDeltas` message. BalanceDeltas within -//! this message are required to have increasing ordinals so that the order of relative balance -//! changes is unambiguous. -//! 2. Store the balances changes with a store handler. You can use the `store_balance_changes` -//! library method directly for this. -//! 3. In the output module, use aggregate_balance_changes to receive an aggregated map of absolute -//! balances. +//! 1. **Mapping (User-Implemented)**: The initial step requires the user to implement a mapping +//! function that extracts `BlockBalanceDeltas` messages. It's crucial that `BalanceDelta` +//! messages within these messages have strictly increasing ordinals, which guarantees the order +//! of balance changes is preserved and unambiguous. This step is not provided by the SDK and +//! must be custom-implemented to suit the specific protocol. +//! +//! 2. **Storing Changes**: Utilize the `store_balance_changes` function to apply relative balance +//! changes. This function handles changes additively, preparing them for final aggregation. +//! +//! 3. **Aggregation**: Use the `aggregate_balance_changes` function to compile the processed +//! changes into a detailed map of absolute balances. This final step produces the comprehensive +//! balance data ready for output modules or further analysis. +//! +//! Through this sequence, the module ensures the transformation from relative to absolute +//! balances is conducted with high fidelity, upholding the integrity of transactional data. + use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}; use itertools::Itertools; use std::{collections::HashMap, str::FromStr}; @@ -19,20 +30,29 @@ use substreams::{ prelude::{BigInt, StoreAdd}, }; -/// Store relative balances changes in a additive manner. +/// Stores relative balance changes in an additive manner. /// -/// Effectively aggregates the relative balances changes into an absolute balances. +/// Aggregates the relative balance changes from a `BlockBalanceDeltas` message into the store +/// in an additive way. This function ensures that balance changes are applied correctly +/// according to the order specified by their ordinal values. Each token's balance changes +/// must have strictly increasing ordinals; otherwise, the function will panic. +/// +/// This method is designed to work in conjunction with `aggregate_balances_changes`, +/// which consumes the data stored by this function. The stored data is intended for use +/// in a "deltas mode" processing pattern, as described in the +/// [Substreams documentation](https://substreams.streamingfast.io/documentation/develop/manifest-modules/types#deltas-mode). /// /// ## Arguments +/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balance changes. It is +/// crucial that the relative balance deltas for each token address have strictly increasing +/// ordinals; the function will panic otherwise. +/// * `store` - An implementation of the `StoreAdd` trait that will be used to add relative balance +/// changes. This store should support the addition of `BigInt` values. /// -/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. Note: -/// relative balance deltas must have strictly increasing ordinals per token address, will panic -/// otherwise. -/// * `store` - An AddStore that will add relative balance changes. -/// -/// This method is meant to be used in combination with `aggregate_balances_changes` -/// which consumes the store filled with this methods in -/// [deltas mode](https://substreams.streamingfast.io/documentation/develop/manifest-modules/types#deltas-mode). +/// ## Panics +/// This function will panic if: +/// - The `component_id` of any delta is not valid UTF-8. +/// - The ordinals for any given token address are not strictly increasing. pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd) { let mut previous_ordinal = HashMap::::new(); deltas @@ -71,14 +91,23 @@ type TxAggregatedBalances = HashMap, (Transaction, HashMap, Bala /// * `balance_store` - A `StoreDeltas` with all changes that occured in the source store module. /// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. /// -/// Reads absolute balance values from the additive store (see `store_balance_changes` -/// on how to create such a store), proceeds to zip them with the relative balance -/// deltas to associate balance values to token and component. +/// This function reads absolute balance values from an additive store (see `store_balance_changes` +/// for how to create such a store). It zips these values with the relative balance deltas to +/// associate balance values with tokens and components, ensuring the last balance change per token +/// per transaction is kept if there are multiple changes. Negative balances are set to 0, adhering +/// to the expectation that absolute balances must be non-negative. /// /// Will keep the last balance change per token per transaction if there are multiple -/// changes. +/// changes. In case a balance ends up being negative, it will be clipped to 0 since +/// absolute balances are expected to be either zero or positive. /// -/// Returns a map of transactions hashes to the full transaction and aggregated +/// ## Panics +/// May panic if the store deltas values are not in the correct format. Values are +/// expected to be utf-8 encoded string integers, which is the default behaviour +/// for substreams stores. +/// +/// ## Returns +/// A map of transactions hashes to a tuple of `Transaction` and aggregated /// absolute balance changes. pub fn aggregate_balances_changes( balance_store: StoreDeltas, @@ -95,7 +124,13 @@ pub fn aggregate_balances_changes( let ascii_string = String::from_utf8(store_delta.new_value.clone()).expect("Invalid UTF-8 sequence"); let balance = BigInt::from_str(&ascii_string).expect("Failed to parse integer"); - let big_endian_bytes_balance = balance.to_bytes_be().1; + + // If the absolute balance is negative, we set it to zero. + let big_endian_bytes_balance = if balance < BigInt::zero() { + BigInt::zero().to_bytes_be().1 + } else { + balance.to_bytes_be().1 + }; ( balance_delta diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs index a99fd60..250da36 100644 --- a/substreams/crates/tycho-substreams/src/contract.rs +++ b/substreams/crates/tycho-substreams/src/contract.rs @@ -72,19 +72,33 @@ impl From for tycho::ContractChange { } } -/// Extracts relevant contract changes from the block. +/// Extracts and aggregates contract changes from a block. /// -/// Contract changes include changes in storage, code and native balance. +/// This function identifies and collects changes to contract storage, code, and native balance for +/// contracts of interest within a given block. It filters contracts based on a user-defined +/// predicate and aggregates changes into a provided mutable map. /// /// ## Arguments -/// -/// * `block` - The block to extract changes from. Must be the extended block model. -/// * `inclusion_predicate` - A predicate function that determines if a contract address is -/// relevant. -/// * `transaction_contract_changes` - A mutable map to store the contract changes in. +/// * `block` - The block from which to extract contract changes, expected to be an extended block +/// model. +/// * `inclusion_predicate` - A closure that determines if a contract's address is of interest for +/// the collection of changes. Only contracts satisfying this predicate are included. +/// * `transaction_contract_changes` - A mutable reference to a map where extracted contract changes +/// are stored. Keyed by transaction index, it aggregates changes into +/// `tycho::TransactionContractChanges`. /// /// ## Panics -/// Will panic in case the detail level of the block is not extended. +/// Panics if the provided block is not an extended block model, as indicated by its detail level. +/// +/// ## Operation +/// The function iterates over transactions and their calls within the block, collecting contract +/// changes (storage, balance, code) that pass the inclusion predicate. Changes are then sorted by +/// their ordinals to maintain the correct sequence of events. Aggregated changes for each contract +/// are stored in `transaction_contract_changes`, categorized by transaction index. +/// +/// Contracts created within the block are tracked to differentiate between new and existing +/// contracts. The aggregation process respects transaction boundaries, ensuring that changes are +/// mapped accurately to their originating transactions. pub fn extract_contract_changes bool>( block: ð::v2::Block, inclusion_predicate: F, diff --git a/substreams/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs index 14ab6f5..fa0fa07 100644 --- a/substreams/crates/tycho-substreams/src/models.rs +++ b/substreams/crates/tycho-substreams/src/models.rs @@ -43,38 +43,50 @@ impl From<&sf::Block> for Block { } impl ProtocolComponent { - /// Creates a new empty `ProtocolComponent` instance. + /// Constructs a new, empty `ProtocolComponent`. /// - /// You can use the `with_*` methods to set the fields in a convience way. + /// Initializes an instance with default values. Use `with_*` methods to populate fields + /// conveniently. + /// + /// ## Parameters + /// - `id`: Identifier for the component. + /// - `tx`: Reference to the associated transaction. pub fn new(id: &str, tx: &Transaction) -> Self { Self { id: id.to_string(), - tokens: vec![], - contracts: vec![], - static_att: vec![], + tokens: Vec::new(), + contracts: Vec::new(), + static_att: Vec::new(), change: ChangeType::Creation.into(), protocol_type: None, tx: Some(tx.clone()), } } - /// Shorthand to create a component with a 1-1 relationship to a contract. + /// Initializes a `ProtocolComponent` with a direct association to a contract. /// - /// Will set the component id to a hex encoded address with a 0x prefix - /// and add the contract to contracts attributes. + /// Sets the component's ID to the hex-encoded address with a `0x` prefix and includes the + /// contract in the contracts list. + /// + /// ## Parameters + /// - `id`: Contract address to be encoded and set as the component's ID. + /// - `tx`: Reference to the associated transaction. pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { Self { id: format!("0x{}", hex::encode(id)), - tokens: vec![], + tokens: Vec::new(), contracts: vec![id.to_vec()], - static_att: vec![], + static_att: Vec::new(), change: ChangeType::Creation.into(), protocol_type: None, tx: Some(tx.clone()), } } - /// Replaces the tokens on this component. + /// Updates the tokens associated with this component. + /// + /// ## Parameters + /// - `tokens`: Slice of byte slices representing the tokens to associate. pub fn with_tokens>(mut self, tokens: &[B]) -> Self { self.tokens = tokens .iter() @@ -83,7 +95,10 @@ impl ProtocolComponent { self } - /// Replaces the contracts associated with this component. + /// Updates the contracts associated with this component. + /// + /// ## Parameters + /// - `contracts`: Slice of byte slices representing the contracts to associate. pub fn with_contracts>(mut self, contracts: &[B]) -> Self { self.contracts = contracts .iter() @@ -92,9 +107,12 @@ impl ProtocolComponent { self } - /// Replaces the static attributes on this component. + /// Updates the static attributes of this component. /// - /// The change type will be set to Creation. + /// Sets the change type to `Creation` for all attributes. + /// + /// ## Parameters + /// - `attributes`: Slice of key-value pairs representing the attributes to set. pub fn with_attributes, V: AsRef<[u8]>>(mut self, attributes: &[(K, V)]) -> Self { self.static_att = attributes .iter() @@ -107,15 +125,19 @@ impl ProtocolComponent { self } - /// Sets the protocol_type on this component. + /// Designates this component as a swap type within the protocol. /// - /// Will set the `financial_type` to FinancialType::Swap and the - /// `attribute_schema` to an empty list. + /// Sets the `protocol_type` accordingly, including `financial_type` as `Swap` and leaving + /// `attribute_schema` empty. + /// + /// ## Parameters + /// - `name`: The name of the swap protocol. + /// - `implementation_type`: The implementation type of the protocol. pub fn as_swap_type(mut self, name: &str, implementation_type: ImplementationType) -> Self { self.protocol_type = Some(ProtocolType { name: name.to_string(), financial_type: FinancialType::Swap.into(), - attribute_schema: vec![], + attribute_schema: Vec::new(), implementation_type: implementation_type.into(), }); self From 3b511233115848a9174c1d7deec1497a7bff5b9a Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 12:52:29 +0000 Subject: [PATCH 31/37] Normalise module names for balancer. This way the module names are in sync with the gitbook docs. --- .gitignore | 2 ++ substreams/ethereum-balancer/src/modules.rs | 10 ++++----- substreams/ethereum-balancer/substreams.yaml | 22 ++++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 2c65d74..8ab5a15 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ target/ .vscode .idea *.log + +substreams/ethereum-template/Cargo.lock diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index b1747b1..af6db11 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -15,7 +15,7 @@ use tycho_substreams::{ const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); #[substreams::handlers::map] -pub fn map_pools_created(block: eth::v2::Block) -> Result { +pub fn map_components(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 { @@ -47,7 +47,7 @@ pub fn map_pools_created(block: eth::v2::Block) -> Result Result { @@ -133,7 +133,7 @@ pub fn map_balance_deltas( /// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the /// store key to ensure that there's a unique balance being tallied for each. #[substreams::handlers::store] -pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { +pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { tycho_substreams::balances::store_balance_changes(deltas, store); } @@ -144,7 +144,7 @@ pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: StoreAddBigInt) /// At the very end, the map can easily be sorted by index to ensure the final /// `BlockContractChanges` is ordered by transactions properly. #[substreams::handlers::map] -pub fn map_changes( +pub fn map_protocol_changes( block: eth::v2::Block, grouped_components: BlockTransactionProtocolComponents, deltas: BlockBalanceDeltas, diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 06f2ee7..9597334 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -9,7 +9,7 @@ binaries: file: ../target/wasm32-unknown-unknown/release/ethereum_balancer.wasm modules: - - name: map_pools_created + - name: map_components kind: map initialBlock: 12369300 inputs: @@ -17,40 +17,40 @@ modules: output: type: proto:tycho.evm.v1.GroupedTransactionProtocolComponents - - name: store_pools_created + - name: store_components kind: store initialBlock: 12369300 updatePolicy: add valueType: int64 inputs: - - map: map_pools_created + - map: map_components - - name: map_balance_deltas + - name: map_relative_balances kind: map initialBlock: 12369300 # An arbitrary block that should change based on your requirements inputs: - source: sf.ethereum.type.v2.Block - - store: store_pools_created + - store: store_components output: type: proto:tycho.evm.v1.BalanceDeltas - - name: store_balance_changes + - name: store_balances kind: store initialBlock: 12369300 updatePolicy: add valueType: bigint inputs: - - map: map_balance_deltas + - map: map_relative_balances - name: map_changes kind: map initialBlock: 12369300 inputs: - source: sf.ethereum.type.v2.Block - - map: map_pools_created - - map: map_balance_deltas - - store: store_pools_created - - store: store_balance_changes + - map: map_components + - map: map_relative_balances + - store: store_components + - store: store_balances mode: deltas # This is the key property that simplifies `BalanceChange` handling output: type: proto:tycho.evm.v1.BlockContractChanges From 2e774053428c5b3967ddc0c8911f24192089162d Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 12:53:12 +0000 Subject: [PATCH 32/37] Update ethereum-template Remove unecessary pb module, import models from tycho-substreams instead. Integrate package directly into workspace. --- substreams/ethereum-template/Cargo.lock | 1135 ----------------- substreams/ethereum-template/Cargo.toml | 11 +- substreams/ethereum-template/src/lib.rs | 8 +- substreams/ethereum-template/src/modules.rs | 12 + substreams/ethereum-template/src/pb/mod.rs | 10 - .../ethereum-template/src/pb/tycho.evm.v1.rs | 183 --- substreams/ethereum-template/substreams.yaml | 13 +- 7 files changed, 23 insertions(+), 1349 deletions(-) delete mode 100644 substreams/ethereum-template/Cargo.lock create mode 100644 substreams/ethereum-template/src/modules.rs delete mode 100644 substreams/ethereum-template/src/pb/mod.rs delete mode 100644 substreams/ethereum-template/src/pb/tycho.evm.v1.rs diff --git a/substreams/ethereum-template/Cargo.lock b/substreams/ethereum-template/Cargo.lock deleted file mode 100644 index ada8eab..0000000 --- a/substreams/ethereum-template/Cargo.lock +++ /dev/null @@ -1,1135 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bigdecimal" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "ethabi" -version = "17.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-rlp", - "impl-serde", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-rlp", - "impl-serde", - "primitive-types", - "uint", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" - -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "pad" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "primitive-types" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" -dependencies = [ - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" -dependencies = [ - "bytes", - "heck", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn 1.0.109", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustix" -version = "0.38.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.41", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "substreams" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3524a4e2931ff6cd58783e62adbd7e44f461752eca0c423793cfb462351f24" -dependencies = [ - "anyhow", - "bigdecimal", - "hex", - "hex-literal", - "num-bigint", - "num-integer", - "num-traits", - "pad", - "prost", - "prost-build", - "prost-types", - "substreams-macro", - "thiserror", -] - -[[package]] -name = "substreams-ethereum" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f45dc04be50b7ca08d6d5c4560ee3eeba16ccaa1c124d0361bb30b5b84e28b" -dependencies = [ - "getrandom", - "num-bigint", - "substreams", - "substreams-ethereum-abigen", - "substreams-ethereum-core", - "substreams-ethereum-derive", -] - -[[package]] -name = "substreams-ethereum-abigen" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c04307913a355aaf2a1bb7186d4bc7e36875f3d4aff77b47e83f1b63b24da55" -dependencies = [ - "anyhow", - "ethabi", - "heck", - "hex", - "prettyplease", - "proc-macro2", - "quote", - "substreams-ethereum-core", - "syn 1.0.109", -] - -[[package]] -name = "substreams-ethereum-core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db9048cc9a66873ab7069ef958c2684994e6ee323da49c186b19156fdb4ca131" -dependencies = [ - "bigdecimal", - "ethabi", - "getrandom", - "num-bigint", - "prost", - "prost-build", - "prost-types", - "substreams", -] - -[[package]] -name = "substreams-ethereum-derive" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e862928bee8653f5c9291ac619c8dc0da14ca61d8cd8d89b3acdbbde4d0bf304" -dependencies = [ - "ethabi", - "heck", - "hex", - "num-bigint", - "proc-macro2", - "quote", - "substreams-ethereum-abigen", - "syn 1.0.109", -] - -[[package]] -name = "substreams-ethereum-template" -version = "0.1.0" -dependencies = [ - "prost", - "substreams", - "substreams-ethereum", -] - -[[package]] -name = "substreams-macro" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c2b15adf5b4d7a6d1a73c73df951a6b2df6fbb4f0b41304dc28c5550ce0ed0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "thiserror" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.41", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" - -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winnow" -version = "0.5.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" -dependencies = [ - "memchr", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] diff --git a/substreams/ethereum-template/Cargo.toml b/substreams/ethereum-template/Cargo.toml index 82ae8f3..fa4ecad 100644 --- a/substreams/ethereum-template/Cargo.toml +++ b/substreams/ethereum-template/Cargo.toml @@ -1,13 +1,14 @@ [package] -name = "substreams-ethereum-template" +name = "ethereum-template" version = "0.1.0" edition = "2021" [lib] -name = "substreams_ethereum_template" +name = "ethereum_template" crate-type = ["cdylib"] [dependencies] -substreams = "0.5" -substreams-ethereum = "0.9" -prost = "0.11" +substreams.workspace = true +substreams-ethereum.workspace = true +prost.workspace = true +tycho-substreams.workspace = true \ No newline at end of file diff --git a/substreams/ethereum-template/src/lib.rs b/substreams/ethereum-template/src/lib.rs index 6e10475..94324fd 100644 --- a/substreams/ethereum-template/src/lib.rs +++ b/substreams/ethereum-template/src/lib.rs @@ -1,13 +1,9 @@ - use substreams_ethereum::pb::eth; - -use pb::tycho::evm::v1::{self as tycho}; - -mod pb; +mod modules; #[substreams::handlers::map] fn map_changes( block: eth::v2::Block, ) -> Result { todo!("Not implemented") -} \ No newline at end of file +} diff --git a/substreams/ethereum-template/src/modules.rs b/substreams/ethereum-template/src/modules.rs new file mode 100644 index 0000000..136d351 --- /dev/null +++ b/substreams/ethereum-template/src/modules.rs @@ -0,0 +1,12 @@ +use std::collections::HashMap; +use substreams_ethereum::pb::eth; +use tycho_substreams::prelude::*; + +#[substreams::handlers::map] +fn map_protocol_changes( + block: eth::v2::Block, +) -> Result { + let mut transaction_contract_changes = Vec::::new(); + // TODO: protocol specific logic goes here + Ok(BlockContractChanges { block: Some((&block).into()), changes: transaction_contract_changes }) +} diff --git a/substreams/ethereum-template/src/pb/mod.rs b/substreams/ethereum-template/src/pb/mod.rs deleted file mode 100644 index 43d8838..0000000 --- a/substreams/ethereum-template/src/pb/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -// @generated -pub mod tycho { - pub mod evm { - // @@protoc_insertion_point(attribute:tycho.evm.v1) - pub mod v1 { - include!("tycho.evm.v1.rs"); - // @@protoc_insertion_point(tycho.evm.v1) - } - } -} diff --git a/substreams/ethereum-template/src/pb/tycho.evm.v1.rs b/substreams/ethereum-template/src/pb/tycho.evm.v1.rs deleted file mode 100644 index b59b5f7..0000000 --- a/substreams/ethereum-template/src/pb/tycho.evm.v1.rs +++ /dev/null @@ -1,183 +0,0 @@ -// @generated -// This file contains the proto definitions for Substreams common to all integrations. - -/// A struct describing a block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Block { - /// The blocks hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The parent blocks hash. - #[prost(bytes="vec", tag="2")] - pub parent_hash: ::prost::alloc::vec::Vec, - /// The block number. - #[prost(uint64, tag="3")] - pub number: u64, - /// The block timestamp. - #[prost(uint64, tag="4")] - pub ts: u64, -} -/// A struct describing a transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transaction { - /// The transaction hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The sender of the transaction. - #[prost(bytes="vec", tag="2")] - pub from: ::prost::alloc::vec::Vec, - /// The receiver of the transaction. - #[prost(bytes="vec", tag="3")] - pub to: ::prost::alloc::vec::Vec, - /// The transactions index within the block. - #[prost(uint64, tag="4")] - pub index: u64, -} -/// A custom struct representing an arbitrary attribute of a protocol component. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Attribute { - /// The name of the attribute. - #[prost(string, tag="1")] - pub name: ::prost::alloc::string::String, - /// The value of the attribute. - #[prost(bytes="vec", tag="2")] - pub value: ::prost::alloc::vec::Vec, - /// The type of change the attribute underwent. - #[prost(enumeration="ChangeType", tag="3")] - pub change: i32, -} -/// A struct describing a part of the protocol. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProtocolComponent { - /// A unique identifier for the component within the protocol. - /// Can be a stringified address or a string describing the trading pair. - #[prost(string, tag="1")] - pub id: ::prost::alloc::string::String, - /// Addresses of the ERC20 tokens used by the component. - #[prost(bytes="vec", repeated, tag="2")] - pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Addresses of the contracts used by the component. - #[prost(bytes="vec", repeated, tag="3")] - pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Attributes of the component. - /// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. - #[prost(message, repeated, tag="4")] - pub static_att: ::prost::alloc::vec::Vec, - /// Type of change the component underwent. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, -} -/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -/// Note that if the ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceChange { - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="1")] - pub token: ::prost::alloc::vec::Vec, - /// The new balance of the token. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - #[prost(bytes="vec", tag="3")] - pub component_id: ::prost::alloc::vec::Vec, -} -/// Enum to specify the type of a change. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum ChangeType { - Unspecified = 0, - Update = 1, - Creation = 2, - Deletion = 3, -} -impl ChangeType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED", - ChangeType::Update => "CHANGE_TYPE_UPDATE", - ChangeType::Creation => "CHANGE_TYPE_CREATION", - ChangeType::Deletion => "CHANGE_TYPE_DELETION", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "CHANGE_TYPE_UPDATE" => Some(Self::Update), - "CHANGE_TYPE_CREATION" => Some(Self::Creation), - "CHANGE_TYPE_DELETION" => Some(Self::Deletion), - _ => None, - } - } -} -// This file contains proto definitions specific to the VM integration. - -/// A key value entry into contract storage. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractSlot { - /// A contract's storage slot. - #[prost(bytes="vec", tag="2")] - pub slot: ::prost::alloc::vec::Vec, - /// The new value for this storage slot. - #[prost(bytes="vec", tag="3")] - pub value: ::prost::alloc::vec::Vec, -} -/// Changes made to a single contract's state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractChange { - /// The contract's address - #[prost(bytes="vec", tag="1")] - pub address: ::prost::alloc::vec::Vec, - /// The new balance of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The new code of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="3")] - pub code: ::prost::alloc::vec::Vec, - /// The changes to this contract's slots, empty sequence indicates no change. - #[prost(message, repeated, tag="4")] - pub slots: ::prost::alloc::vec::Vec, - /// Whether this is an update, a creation or a deletion. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, -} -/// A set of changes aggregated by transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionContractChanges { - /// The transaction instance that results in the changes. - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - /// Contains the changes induced by the above transaction, aggregated on a per-contract basis. - #[prost(message, repeated, tag="2")] - pub contract_changes: ::prost::alloc::vec::Vec, - /// An array of newly added components. - #[prost(message, repeated, tag="3")] - pub component_changes: ::prost::alloc::vec::Vec, - /// An array of balance changes to components. - #[prost(message, repeated, tag="4")] - pub balance_changes: ::prost::alloc::vec::Vec, -} -/// A set of transaction changes within a single block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockContractChanges { - /// The block for which these changes are collectively computed. - #[prost(message, optional, tag="1")] - pub block: ::core::option::Option, - /// The set of transaction changes observed in the specified block. - #[prost(message, repeated, tag="2")] - pub changes: ::prost::alloc::vec::Vec, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-template/substreams.yaml b/substreams/ethereum-template/substreams.yaml index b3fa3fb..de5dcbf 100644 --- a/substreams/ethereum-template/substreams.yaml +++ b/substreams/ethereum-template/substreams.yaml @@ -1,22 +1,15 @@ specVersion: v0.1.0 package: - name: "substreams_ethereum_template" + name: "ethereum_template" version: v0.1.0 -protobuf: - files: - - vm.proto - - common.proto - importPaths: - - ../../proto/tycho/evm/v1/ - binaries: default: type: wasm/rust-v1 - file: ../../target/wasm32-unknown-unknown/substreams/substreams_ethereum_template.wasm + file: ../target/wasm32-unknown-unknown/release/ethereum_template.wasm modules: - - name: map_changes + - name: map_protocol_changes kind: map inputs: - source: sf.ethereum.type.v2.Block From d972da244f291a8e39dcc42b15028e252526a3a8 Mon Sep 17 00:00:00 2001 From: kayibal Date: Thu, 14 Mar 2024 13:05:06 +0000 Subject: [PATCH 33/37] Remove outdated readme. Add docs about releasing. --- substreams/Readme.md | 107 +++++++------------------------------------ 1 file changed, 16 insertions(+), 91 deletions(-) diff --git a/substreams/Readme.md b/substreams/Readme.md index 530d858..0ceaea5 100644 --- a/substreams/Readme.md +++ b/substreams/Readme.md @@ -1,99 +1,24 @@ -# Subtreams packages +# Substreams Indexing Integrations -This directory contains all substream packages that are used to index integrated protocols across different blockchains. +Please refer to the official [Substreams Indexing](https://app.gitbook.com/o/9wMvRDQIhk1xOsIZ0Zde/s/Yx9kvxtpT2xWdzvFiB3t/indexing/substreams-integration) docs. -## Adding a new package +## Release -To add a new package add a folder. The naming convention is `[CHAIN]-[PROTOCOL_SYSTEM]`. +To release a package simply tag a commit with the package name and its version: +e.g. `ethereum-balancer-0.1.0`. This will create a release and automatically build +and push the spkg into our registry. -### Manifest -In this new folder add a manifest file `substreams.yaml`. You can use the template below to get started: +### Note +The CD pipeline will error if the Cargo version is not the same as the version in +the tag. -```yaml -specVersion: v0.1.0 -package: - name: 'substreams_[CHAIN]_[PROTOCOL_SYSTEM]' - version: v0.1.0 +Releases are immutable so do no try to delete tags or build the same release twice +since this will error. -protobuf: - files: - - vm.proto - - common.proto - # You can specify any internal proto files here - importPaths: - - ../../proto/tycho/evm/v1/ - # Any private message types only used in internal modules - # can remain local to the folder. - - ./proto +### Pre release -binaries: - default: - type: wasm/rust-v1 - # this points to the workspace target directory we use a special - # substreams build profile to optimise wasm binaries - file: ../../target/wasm32-unknown-unknown/substreams/substreams_[CHAIN]_[PROTOCOL_SYSTEM].wasm +To create a pre release for testing in dev you can start CD pipeline manually supplying +the package you'd like to pre release. This will create a +`[package]-[semver].pre-[commit-sha]` release in our spkg repository which you can use +to run the substream´. -modules: - - name: map_changes - kind: map - inputs: - - source: sf.ethereum.type.v2.Block - output: - type: proto:tycho.evm.state.v1.BlockContractChanges -``` - -Substreams packages are Rust crates so we also need a `cargo.toml`. -The example from the official docs will serve us just well: - -```toml -[package] -name = "substreams-[CHAIN]-[PROTOCOL_SYSTEM]" -version = "0.1.0" -edition = "2021" - -[lib] -name = "substreams_[CHAIN]_[PROTOCOL_SYSTEM]" -crate-type = ["cdylib"] - -[dependencies] -substreams = "0.5" -substreams-ethereum = "0.9" -prost = "0.11" - -``` - -There are already some generated rust files in the `src/pb` directory. These are generated -from the protobuf files in the `/proto/tycho/evm/v1` directory. They specify the output protobuf messages -we want to generate. The input Block is specified by the subtreams crate, specifically the [sf.ethereum.type.v2.Block](https://github.com/streamingfast/substreams-ethereum/blob/develop/core/src/pb/sf.ethereum.type.v2.rs) message. - -You can define your own protobuf messages, make a new directory `/substreams/[CHAIN]-[PROTOCOL]/proto` for them. - - -Now we can generate the Rust protobuf code: - -``` -substreams protogen substreams.yaml --exclude-paths="sf/substreams,google" -``` - -The command above should put the generate rust files under `/src/pb`. You -can start using these now in your module handlers: See -the [official substreams documentation](https://thegraph.com/docs/en/substreams/getting-started/quickstart/#create-substreams-module-handlers) -on -how to implement module handlers. - -You can also look into already existing substreams packages to see how it -is done. E.g. [ethereum-ambient](./ethereum-ambient/) provides a pretty good -example of how to get access to raw contract storage. - -# Tests - -To create a block test asset for ethereum do the following: - -- Follow [this tutorial](https://substreams.streamingfast.io/tutorials/overview/map_block_meta_module). Make sure you - set up the substreams-explorer repo in the same directory as this repo. - - Comment out `image: ./ethereum.png` in `ethereum-explorer/substreams.yaml` - - Add `prost-types = "0.11.0"` to `ethereum-explorer/Cargo.toml` -- Make sure you set up your key env vars. -- Run `sh scripts/download-ethereum-block-to-s3 BLOCK_NUMBER` - -Do not commit the block files (they are quite big). \ No newline at end of file From 3895a3332cd55ee6c7a5c9373343ff1b6dff8f58 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:38:36 +0100 Subject: [PATCH 34/37] Fix bugs in balance substreams --- substreams/ethereum-balancer/src/modules.rs | 22 +++++++------------- substreams/ethereum-balancer/substreams.yaml | 10 ++++++++- substreams/ethereum-template/substreams.yaml | 8 +++++++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs index af6db11..565c672 100644 --- a/substreams/ethereum-balancer/src/modules.rs +++ b/substreams/ethereum-balancer/src/modules.rs @@ -75,13 +75,10 @@ pub fn map_relative_balances( if let Some(ev) = abi::vault::events::PoolBalanceChanged::match_and_decode(vault_log.log) { - let component_id = - format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) - .as_bytes() - .to_vec(); + let component_id = format!("0x{}", hex::encode(&ev.pool_id[..20])); if store - .get_last(format!("pool:{}", hex::encode(&component_id))) + .get_last(format!("pool:{}", component_id)) .is_some() { for (token, delta) in ev.tokens.iter().zip(ev.deltas.iter()) { @@ -90,18 +87,15 @@ pub fn map_relative_balances( tx: Some(vault_log.receipt.transaction.into()), token: token.to_vec(), delta: delta.to_signed_bytes_be(), - component_id: component_id.clone(), + component_id: component_id.as_bytes().to_vec(), }); } } } else if let Some(ev) = abi::vault::events::Swap::match_and_decode(vault_log.log) { - let component_id = - format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) - .as_bytes() - .to_vec(); + let component_id = format!("0x{}", hex::encode(&ev.pool_id[..20])); if store - .get_last(format!("pool:{}", hex::encode(&component_id))) + .get_last(format!("pool:{}", component_id)) .is_some() { deltas.extend_from_slice(&[ @@ -110,14 +104,14 @@ pub fn map_relative_balances( tx: Some(vault_log.receipt.transaction.into()), token: ev.token_in.to_vec(), delta: ev.amount_in.to_signed_bytes_be(), - component_id: component_id.clone(), + component_id: component_id.as_bytes().to_vec(), }, BalanceDelta { ord: vault_log.ordinal(), tx: Some(vault_log.receipt.transaction.into()), token: ev.token_out.to_vec(), delta: ev.amount_out.neg().to_signed_bytes_be(), - component_id, + component_id: component_id.as_bytes().to_vec(), }, ]); } @@ -188,7 +182,7 @@ pub fn map_protocol_changes( &block, |addr| { components_store - .get_last(format!("pool:{0}", hex::encode(addr))) + .get_last(format!("pool:0x{0}", hex::encode(addr))) .is_some() }, &mut transaction_contract_changes, diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml index 9597334..99810e2 100644 --- a/substreams/ethereum-balancer/substreams.yaml +++ b/substreams/ethereum-balancer/substreams.yaml @@ -3,6 +3,14 @@ package: name: "ethereum_balancer" version: v0.1.0 +protobuf: + files: + - tycho/evm/v1/vm.proto + - tycho/evm/v1/common.proto + - tycho/evm/v1/utils.proto + importPaths: + - ../../proto + binaries: default: type: wasm/rust-v1 @@ -42,7 +50,7 @@ modules: inputs: - map: map_relative_balances - - name: map_changes + - name: map_protocol_changes kind: map initialBlock: 12369300 inputs: diff --git a/substreams/ethereum-template/substreams.yaml b/substreams/ethereum-template/substreams.yaml index de5dcbf..903f44a 100644 --- a/substreams/ethereum-template/substreams.yaml +++ b/substreams/ethereum-template/substreams.yaml @@ -3,6 +3,14 @@ package: name: "ethereum_template" version: v0.1.0 +protobuf: + files: + - tycho/evm/v1/vm.proto + - tycho/evm/v1/common.proto + - tycho/evm/v1/utils.proto + importPaths: + - ../../proto + binaries: default: type: wasm/rust-v1 From 3dc290c3df35318112db04c80f3dc3d97259c2ad Mon Sep 17 00:00:00 2001 From: pistomat Date: Wed, 27 Mar 2024 10:31:00 +0100 Subject: [PATCH 35/37] Formatting --- docs/logic/vm-integration/ethereum-solidity.md | 4 ++-- evm/src/balancer-v2/BalancerV2SwapAdapter.sol | 1 - evm/src/balancer-v2/manifest.yaml | 12 ++++++------ evm/src/template/TemplateSwapAdapter.sol | 1 - evm/src/template/manifest.yaml | 4 ++-- evm/src/uniswap-v2/manifest.yaml | 16 ++-------------- 6 files changed, 12 insertions(+), 26 deletions(-) diff --git a/docs/logic/vm-integration/ethereum-solidity.md b/docs/logic/vm-integration/ethereum-solidity.md index 0d6133a..f7bf759 100644 --- a/docs/logic/vm-integration/ethereum-solidity.md +++ b/docs/logic/vm-integration/ethereum-solidity.md @@ -43,7 +43,7 @@ contract: instances: - chain: name: mainnet - id: 0 + id: 1 # Arguments passed to the constructor when building the contract arguments: - "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" @@ -57,8 +57,8 @@ tests: buy_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" block: 17000000 chain: - id: 0 name: mainnet + id: 1 ``` #### Price (optional) diff --git a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol index 56d1d6e..6413013 100644 --- a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol +++ b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol @@ -1,5 +1,4 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -pragma experimental ABIEncoderV2; pragma solidity ^0.8.13; import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; diff --git a/evm/src/balancer-v2/manifest.yaml b/evm/src/balancer-v2/manifest.yaml index 0f985e9..8a01c49 100644 --- a/evm/src/balancer-v2/manifest.yaml +++ b/evm/src/balancer-v2/manifest.yaml @@ -1,6 +1,6 @@ # information about the author helps us reach out in case of issues. author: - name: Propellerheads.xyz + name: Matt email: pistomat@propellerheads.xyz # Protocol Constants @@ -19,7 +19,7 @@ contract: BalancerV2SwapAdapter.sol instances: - chain: name: mainnet - id: 0 + id: 1 arguments: - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" @@ -27,10 +27,10 @@ instances: # getTokens are not implemented. tests: instances: - - pool_id: "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc" - sell_token: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - buy_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + - pool_id: "0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014" + sell_token: "0xba100000625a3754423978a60c9317c58a424e3D" + buy_token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" block: 17000000 chain: - id: 0 name: mainnet + id: 1 diff --git a/evm/src/template/TemplateSwapAdapter.sol b/evm/src/template/TemplateSwapAdapter.sol index 5c8d638..e7f1dcc 100644 --- a/evm/src/template/TemplateSwapAdapter.sol +++ b/evm/src/template/TemplateSwapAdapter.sol @@ -1,5 +1,4 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -pragma experimental ABIEncoderV2; pragma solidity ^0.8.13; import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; diff --git a/evm/src/template/manifest.yaml b/evm/src/template/manifest.yaml index 7343007..069da33 100644 --- a/evm/src/template/manifest.yaml +++ b/evm/src/template/manifest.yaml @@ -19,7 +19,7 @@ contract: TemplateSwapAdapter.sol instances: - chain: name: mainnet - id: 0 + id: 1 arguments: - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" @@ -32,5 +32,5 @@ tests: buy_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" block: 17000000 chain: - id: 0 name: mainnet + id: 1 diff --git a/evm/src/uniswap-v2/manifest.yaml b/evm/src/uniswap-v2/manifest.yaml index a6f469c..7c68477 100644 --- a/evm/src/uniswap-v2/manifest.yaml +++ b/evm/src/uniswap-v2/manifest.yaml @@ -1,6 +1,6 @@ # information about the author helps us reach out in case of issues. author: - name: Propellerheads.xyz + name: Alan email: alan@propellerheads.xyz # Protocol Constants @@ -19,18 +19,6 @@ contract: UniswapV2SwapAdapter.sol instances: - chain: name: mainnet - id: 0 + id: 1 arguments: - "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" - -# Specify some automatic test cases in case getPoolIds and -# getTokens are not implemented. -tests: - instances: - - pool_id: "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc" - sell_token: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - buy_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - block: 17000000 - chain: - id: 0 - name: mainnet From 87c0c8baba571782099515b760ba31dfbfb6bb6b Mon Sep 17 00:00:00 2001 From: pistomat Date: Wed, 27 Mar 2024 10:43:02 +0100 Subject: [PATCH 36/37] chore: forge fmt --- evm/src/balancer-v2/BalancerV2SwapAdapter.sol | 5 +- evm/src/integral/IntegralSwapAdapter.sol | 351 ++++++++++-------- evm/src/uniswap-v2/UniswapV2SwapAdapter.sol | 5 +- evm/test/IntegralSwapAdapter.t.sol | 129 +++---- evm/test/TemplateSwapAdapter.t.sol | 8 +- evm/test/UniswapV2SwapAdapter.t.sol | 4 +- 6 files changed, 271 insertions(+), 231 deletions(-) diff --git a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol index 6413013..e373649 100644 --- a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol +++ b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol @@ -477,9 +477,8 @@ interface IVault { uint256 lastChangeBlock ); - enum SwapKind - /// The number of tokens to send to the Pool is known - { + enum SwapKind { + /// The number of tokens to send to the Pool is known GIVEN_IN, /// The number of tokens to take from the Pool is known GIVEN_OUT diff --git a/evm/src/integral/IntegralSwapAdapter.sol b/evm/src/integral/IntegralSwapAdapter.sol index 4797132..b79f1be 100644 --- a/evm/src/integral/IntegralSwapAdapter.sol +++ b/evm/src/integral/IntegralSwapAdapter.sol @@ -3,12 +3,15 @@ pragma solidity ^0.8.13; import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; -import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeERC20} from + "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -/// @dev Integral submitted deadline of 3600 seconds (1 hour) to Paraswap, but it is not strictly necessary to be this long -/// as the contract allows less durations, we use 1000 seconds (15 minutes) as a deadline +/// @dev Integral submitted deadline of 3600 seconds (1 hour) to Paraswap, but +/// it is not strictly necessary to be this long +/// as the contract allows less durations, we use 1000 seconds (15 minutes) as a +/// deadline uint256 constant SWAP_DEADLINE_SEC = 1000; -uint256 constant STANDARD_TOKEN_DECIMALS = 10**18; +uint256 constant STANDARD_TOKEN_DECIMALS = 10 ** 18; /// @title Integral Swap Adapter contract IntegralSwapAdapter is ISwapAdapter { @@ -21,12 +24,18 @@ contract IntegralSwapAdapter is ISwapAdapter { } /// @inheritdoc ISwapAdapter - /// @dev Integral always relies on a single pool linked to the factory to map two pairs, and does not use routing - /// we can then use getPriceByTokenAddresses() instead of getPriceByPairAddresses() - /// as they both return the same value and the first also handles the order of tokens inside. - /// @dev Since the price of a token is determined externally by Integral Oracles and not by reserves - /// it will always be the same (pre and post trade) and independent of the amounts swapped, - /// but we still return an array of length=specifiedAmounts.length with same values to make sure the return value is the expected from caller. + /// @dev Integral always relies on a single pool linked to the factory to + /// map two pairs, and does not use routing + /// we can then use getPriceByTokenAddresses() instead of + /// getPriceByPairAddresses() + /// as they both return the same value and the first also handles the order + /// of tokens inside. + /// @dev Since the price of a token is determined externally by Integral + /// Oracles and not by reserves + /// it will always be the same (pre and post trade) and independent of the + /// amounts swapped, + /// but we still return an array of length=specifiedAmounts.length with same + /// values to make sure the return value is the expected from caller. function price( bytes32, IERC20 _sellToken, @@ -34,8 +43,9 @@ contract IntegralSwapAdapter is ISwapAdapter { uint256[] memory _specifiedAmounts ) external view override returns (Fraction[] memory _prices) { _prices = new Fraction[](_specifiedAmounts.length); - Fraction memory price = getPriceAt(address(_sellToken), address(_buyToken)); - + Fraction memory price = + getPriceAt(address(_sellToken), address(_buyToken)); + for (uint256 i = 0; i < _specifiedAmounts.length; i++) { _prices[i] = price; } @@ -54,12 +64,12 @@ contract IntegralSwapAdapter is ISwapAdapter { } uint256 gasBefore = gasleft(); - if (side == OrderSide.Sell) { // sell - trade.calculatedAmount = - sell(sellToken, buyToken, specifiedAmount); - } else { // buy - trade.calculatedAmount = - buy(sellToken, buyToken, specifiedAmount); + if (side == OrderSide.Sell) { + // sell + trade.calculatedAmount = sell(sellToken, buyToken, specifiedAmount); + } else { + // buy + trade.calculatedAmount = buy(sellToken, buyToken, specifiedAmount); } trade.gasUsed = gasBefore - gasleft(); trade.price = getPriceAt(address(sellToken), address(buyToken)); @@ -72,21 +82,17 @@ contract IntegralSwapAdapter is ISwapAdapter { override returns (uint256[] memory limits) { - ( - , - , - , - uint256 limitMax0, - , - uint256 limitMax1 - ) = relayer.getPoolState(address(sellToken), address(buyToken)); + (,,, uint256 limitMax0,, uint256 limitMax1) = + relayer.getPoolState(address(sellToken), address(buyToken)); limits = new uint256[](2); limits[0] = limitMax0; limits[1] = limitMax1; - /** - * @dev minLimits in integral are the args: 2(for sellToken, the one before limitMax0) - * and 4(for buyToken, the one before limitMax1) of the function relayer.getPoolState(sellToken, buyToken); + /** + * @dev minLimits in integral are the args: 2(for sellToken, the one + * before limitMax0) + * and 4(for buyToken, the one before limitMax1) of the function + * relayer.getPoolState(sellToken, buyToken); * an implementation of them can be found in the test of this adapter */ } @@ -141,12 +147,12 @@ contract IntegralSwapAdapter is ISwapAdapter { /// @param buyToken The address of the token being bought. /// @param amount The amount to be traded. /// @return uint256 The amount of tokens received. - function sell( - IERC20 sellToken, - IERC20 buyToken, - uint256 amount - ) internal returns (uint256) { - uint256 amountOut = relayer.quoteSell(address(sellToken), address(buyToken), amount); + function sell(IERC20 sellToken, IERC20 buyToken, uint256 amount) + internal + returns (uint256) + { + uint256 amountOut = + relayer.quoteSell(address(sellToken), address(buyToken), amount); if (amountOut == 0) { revert Unavailable("AmountOut is zero!"); } @@ -154,15 +160,17 @@ contract IntegralSwapAdapter is ISwapAdapter { sellToken.safeTransferFrom(msg.sender, address(this), amount); sellToken.safeIncreaseAllowance(address(relayer), amount); - relayer.sell(ITwapRelayer.SellParams({ - tokenIn: address(sellToken), - tokenOut: address(buyToken), - wrapUnwrap: false, - to: msg.sender, - submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), - amountIn: amount, - amountOutMin: amountOut - })); + relayer.sell( + ITwapRelayer.SellParams({ + tokenIn: address(sellToken), + tokenOut: address(buyToken), + wrapUnwrap: false, + to: msg.sender, + submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), + amountIn: amount, + amountOutMin: amountOut + }) + ); return amountOut; } @@ -172,12 +180,13 @@ contract IntegralSwapAdapter is ISwapAdapter { /// @param buyToken The address of the token being bought. /// @param amountBought The amount of buyToken tokens to buy. /// @return uint256 The amount of tokens received. - function buy( - IERC20 sellToken, - IERC20 buyToken, - uint256 amountBought - ) internal returns (uint256) { - uint256 amountIn = relayer.quoteBuy(address(sellToken), address(buyToken), amountBought); + function buy(IERC20 sellToken, IERC20 buyToken, uint256 amountBought) + internal + returns (uint256) + { + uint256 amountIn = relayer.quoteBuy( + address(sellToken), address(buyToken), amountBought + ); if (amountIn == 0) { revert Unavailable("AmountIn is zero!"); } @@ -185,15 +194,17 @@ contract IntegralSwapAdapter is ISwapAdapter { sellToken.safeTransferFrom(msg.sender, address(this), amountIn); sellToken.safeIncreaseAllowance(address(relayer), amountIn); - relayer.buy(ITwapRelayer.BuyParams({ - tokenIn: address(sellToken), - tokenOut: address(buyToken), - wrapUnwrap: false, - to: msg.sender, - submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), - amountInMax: amountIn, - amountOut: amountBought - })); + relayer.buy( + ITwapRelayer.BuyParams({ + tokenIn: address(sellToken), + tokenOut: address(buyToken), + wrapUnwrap: false, + to: msg.sender, + submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), + amountInMax: amountIn, + amountOut: amountBought + }) + ); return amountIn; } @@ -201,30 +212,43 @@ contract IntegralSwapAdapter is ISwapAdapter { /// @notice Get swap price including fee /// @param sellToken token to sell /// @param buyToken token to buy - function getPriceAt(address sellToken, address buyToken) internal view returns(Fraction memory) { - uint256 priceWithoutFee = relayer.getPriceByTokenAddresses(address(sellToken), address(buyToken)); + function getPriceAt(address sellToken, address buyToken) + internal + view + returns (Fraction memory) + { + uint256 priceWithoutFee = relayer.getPriceByTokenAddresses( + address(sellToken), address(buyToken) + ); ITwapFactory factory = ITwapFactory(relayer.factory()); - address pairAddress = factory.getPair(address(sellToken), address(buyToken)); + address pairAddress = + factory.getPair(address(sellToken), address(buyToken)); // get swapFee formatted; swapFee is a constant - uint256 swapFeeFormatted = (STANDARD_TOKEN_DECIMALS - relayer.swapFee(pairAddress)); + uint256 swapFeeFormatted = + (STANDARD_TOKEN_DECIMALS - relayer.swapFee(pairAddress)); // get token decimals - uint256 sellTokenDecimals = 10**ERC20(sellToken).decimals(); - uint256 buyTokenDecimals = 10**ERC20(buyToken).decimals(); + uint256 sellTokenDecimals = 10 ** ERC20(sellToken).decimals(); + uint256 buyTokenDecimals = 10 ** ERC20(buyToken).decimals(); /** * @dev - * Denominator works as a "standardizer" for the price rather than a reserve value - * as Integral takes prices from oracles and do not operate with reserves; + * Denominator works as a "standardizer" for the price rather than a + * reserve value + * as Integral takes prices from oracles and do not operate with + * reserves; * it is therefore used to maintain integrity for the Fraction division, - * as numerator and denominator could have different token decimals(es. ETH(18)-USDC(6)). - * Both numerator and denominator are also multiplied by STANDARD_TOKEN_DECIMALS + * as numerator and denominator could have different token decimals(es. + * ETH(18)-USDC(6)). + * Both numerator and denominator are also multiplied by + * STANDARD_TOKEN_DECIMALS * to ensure that precision losses are minimized or null. */ return Fraction( priceWithoutFee * STANDARD_TOKEN_DECIMALS, - STANDARD_TOKEN_DECIMALS * sellTokenDecimals * swapFeeFormatted / buyTokenDecimals + STANDARD_TOKEN_DECIMALS * sellTokenDecimals * swapFeeFormatted + / buyTokenDecimals ); } } @@ -276,8 +300,12 @@ interface ITwapRelayer { uint256 amountIn, uint256 indexed delayOrderId ); - event RebalanceSellWithOneInch(address indexed oneInchRouter, uint256 gas, bytes data); - event OneInchRouterWhitelisted(address indexed oneInchRouter, bool whitelisted); + event RebalanceSellWithOneInch( + address indexed oneInchRouter, uint256 gas, bytes data + ); + event OneInchRouterWhitelisted( + address indexed oneInchRouter, bool whitelisted + ); function factory() external pure returns (address); @@ -289,7 +317,10 @@ interface ITwapRelayer { function rebalancer() external view returns (address); - function isOneInchRouterWhitelisted(address oneInchRouter) external view returns (bool); + function isOneInchRouterWhitelisted(address oneInchRouter) + external + view + returns (bool); function setOwner(address _owner) external; @@ -309,19 +340,26 @@ interface ITwapRelayer { function tokenLimitMin(address token) external pure returns (uint256); - function tokenLimitMaxMultiplier(address token) external pure returns (uint256); + function tokenLimitMaxMultiplier(address token) + external + pure + returns (uint256); function tolerance(address pair) external pure returns (uint16); function setRebalancer(address _rebalancer) external; - function whitelistOneInchRouter(address oneInchRouter, bool whitelisted) external; + function whitelistOneInchRouter(address oneInchRouter, bool whitelisted) + external; function getTolerance(address pair) external pure returns (uint16); function getTokenLimitMin(address token) external pure returns (uint256); - function getTokenLimitMaxMultiplier(address token) external pure returns (uint256); + function getTokenLimitMaxMultiplier(address token) + external + pure + returns (uint256); function getTwapInterval(address pair) external pure returns (uint32); @@ -335,7 +373,10 @@ interface ITwapRelayer { uint32 submitDeadline; } - function sell(SellParams memory sellParams) external payable returns (uint256 orderId); + function sell(SellParams memory sellParams) + external + payable + returns (uint256 orderId); struct BuyParams { address tokenIn; @@ -347,18 +388,20 @@ interface ITwapRelayer { uint32 submitDeadline; } - function buy(BuyParams memory buyParams) external payable returns (uint256 orderId); + function buy(BuyParams memory buyParams) + external + payable + returns (uint256 orderId); function getPriceByPairAddress(address pair, bool inverted) external view - returns ( - uint8 xDecimals, - uint8 yDecimals, - uint256 price - ); + returns (uint8 xDecimals, uint8 yDecimals, uint256 price); - function getPriceByTokenAddresses(address tokenIn, address tokenOut) external view returns (uint256 price); + function getPriceByTokenAddresses(address tokenIn, address tokenOut) + external + view + returns (uint256 price); function getPoolState(address token0, address token1) external @@ -372,29 +415,19 @@ interface ITwapRelayer { uint256 limitMax1 ); - function quoteSell( - address tokenIn, - address tokenOut, - uint256 amountIn - ) external view returns (uint256 amountOut); + function quoteSell(address tokenIn, address tokenOut, uint256 amountIn) + external + view + returns (uint256 amountOut); - function quoteBuy( - address tokenIn, - address tokenOut, - uint256 amountOut - ) external view returns (uint256 amountIn); + function quoteBuy(address tokenIn, address tokenOut, uint256 amountOut) + external + view + returns (uint256 amountIn); - function approve( - address token, - uint256 amount, - address to - ) external; + function approve(address token, uint256 amount, address to) external; - function withdraw( - address token, - uint256 amount, - address to - ) external; + function withdraw(address token, uint256 amount, address to) external; function rebalanceSellWithDelay( address tokenIn, @@ -412,12 +445,17 @@ interface ITwapRelayer { } interface ITwapFactory { - event PairCreated(address indexed token0, address indexed token1, address pair, uint256); + event PairCreated( + address indexed token0, address indexed token1, address pair, uint256 + ); event OwnerSet(address owner); function owner() external view returns (address); - function getPair(address tokenA, address tokenB) external view returns (address pair); + function getPair(address tokenA, address tokenB) + external + view + returns (address pair); function allPairs(uint256) external view returns (address pair); @@ -432,41 +470,19 @@ interface ITwapFactory { function setOwner(address) external; - function setMintFee( - address tokenA, - address tokenB, - uint256 fee - ) external; + function setMintFee(address tokenA, address tokenB, uint256 fee) external; - function setBurnFee( - address tokenA, - address tokenB, - uint256 fee - ) external; + function setBurnFee(address tokenA, address tokenB, uint256 fee) external; - function setSwapFee( - address tokenA, - address tokenB, - uint256 fee - ) external; + function setSwapFee(address tokenA, address tokenB, uint256 fee) external; - function setOracle( - address tokenA, - address tokenB, - address oracle - ) external; + function setOracle(address tokenA, address tokenB, address oracle) + external; - function setTrader( - address tokenA, - address tokenB, - address trader - ) external; + function setTrader(address tokenA, address tokenB, address trader) + external; - function collect( - address tokenA, - address tokenB, - address to - ) external; + function collect(address tokenA, address tokenB, address to) external; function withdraw( address tokenA, @@ -491,20 +507,39 @@ interface ITwapERC20 is IERC20 { bytes32 s ) external; - function increaseAllowance(address spender, uint256 addedValue) external returns (bool); + function increaseAllowance(address spender, uint256 addedValue) + external + returns (bool); - function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); + function decreaseAllowance(address spender, uint256 subtractedValue) + external + returns (bool); } interface IReserves { - function getReserves() external view returns (uint112 reserve0, uint112 reserve1); + function getReserves() + external + view + returns (uint112 reserve0, uint112 reserve1); function getFees() external view returns (uint256 fee0, uint256 fee1); } interface ITwapPair is ITwapERC20, IReserves { - event Mint(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 liquidityOut, address indexed to); - event Burn(address indexed sender, uint256 amount0Out, uint256 amount1Out, uint256 liquidityIn, address indexed to); + event Mint( + address indexed sender, + uint256 amount0In, + uint256 amount1In, + uint256 liquidityOut, + address indexed to + ); + event Burn( + address indexed sender, + uint256 amount0Out, + uint256 amount1Out, + uint256 liquidityIn, + address indexed to + ); event Swap( address indexed sender, uint256 amount0In, @@ -541,7 +576,9 @@ interface ITwapPair is ITwapERC20, IReserves { function setBurnFee(uint256 fee) external; - function burn(address to) external returns (uint256 amount0, uint256 amount1); + function burn(address to) + external + returns (uint256 amount0, uint256 amount1); function swapFee() external view returns (uint256); @@ -569,15 +606,33 @@ interface ITwapPair is ITwapERC20, IReserves { address _trader ) external; - function getSwapAmount0In(uint256 amount1Out, bytes calldata data) external view returns (uint256 swapAmount0In); + function getSwapAmount0In(uint256 amount1Out, bytes calldata data) + external + view + returns (uint256 swapAmount0In); - function getSwapAmount1In(uint256 amount0Out, bytes calldata data) external view returns (uint256 swapAmount1In); + function getSwapAmount1In(uint256 amount0Out, bytes calldata data) + external + view + returns (uint256 swapAmount1In); - function getSwapAmount0Out(uint256 amount1In, bytes calldata data) external view returns (uint256 swapAmount0Out); + function getSwapAmount0Out(uint256 amount1In, bytes calldata data) + external + view + returns (uint256 swapAmount0Out); - function getSwapAmount1Out(uint256 amount0In, bytes calldata data) external view returns (uint256 swapAmount1Out); + function getSwapAmount1Out(uint256 amount0In, bytes calldata data) + external + view + returns (uint256 swapAmount1Out); - function getDepositAmount0In(uint256 amount0, bytes calldata data) external view returns (uint256 depositAmount0In); + function getDepositAmount0In(uint256 amount0, bytes calldata data) + external + view + returns (uint256 depositAmount0In); - function getDepositAmount1In(uint256 amount1, bytes calldata data) external view returns (uint256 depositAmount1In); + function getDepositAmount1In(uint256 amount1, bytes calldata data) + external + view + returns (uint256 depositAmount1In); } diff --git a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol index 16a1673..8704677 100644 --- a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol +++ b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol @@ -87,10 +87,9 @@ contract UniswapV2SwapAdapter is ISwapAdapter { buy(pair, sellToken, zero2one, r0, r1, specifiedAmount); } trade.gasUsed = gasBefore - gasleft(); - if(side == OrderSide.Sell) { + if (side == OrderSide.Sell) { trade.price = getPriceAt(specifiedAmount, r0, r1); - } - else { + } else { trade.price = getPriceAt(trade.calculatedAmount, r0, r1); } } diff --git a/evm/test/IntegralSwapAdapter.t.sol b/evm/test/IntegralSwapAdapter.t.sol index 3d41885..dcba8fb 100644 --- a/evm/test/IntegralSwapAdapter.t.sol +++ b/evm/test/IntegralSwapAdapter.t.sol @@ -1,103 +1,97 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.13; - + import "forge-std/Test.sol"; import "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import "src/interfaces/ISwapAdapterTypes.sol"; import "src/libraries/FractionMath.sol"; import "src/integral/IntegralSwapAdapter.sol"; - + contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes { using FractionMath for Fraction; - + IntegralSwapAdapter adapter; ITwapRelayer relayer; IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); IERC20 constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); - address constant USDC_WETH_PAIR = - 0x2fe16Dd18bba26e457B7dD2080d5674312b026a2; - address constant relayerAddress = - 0xd17b3c9784510E33cD5B87b490E79253BcD81e2E; - + address constant USDC_WETH_PAIR = 0x2fe16Dd18bba26e457B7dD2080d5674312b026a2; + address constant relayerAddress = 0xd17b3c9784510E33cD5B87b490E79253BcD81e2E; + uint256 constant TEST_ITERATIONS = 100; - + function setUp() public { uint256 forkBlock = 18835309; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); adapter = new IntegralSwapAdapter(relayerAddress); relayer = ITwapRelayer(relayerAddress); - + vm.label(address(WETH), "WETH"); vm.label(address(USDC), "USDC"); vm.label(address(USDC_WETH_PAIR), "USDC_WETH_PAIR"); } - + function testPriceFuzzIntegral(uint256 amount0, uint256 amount1) public { bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); uint256[] memory limits = adapter.getLimits(pair, USDC, WETH); vm.assume(amount0 < limits[0]); vm.assume(amount1 < limits[1]); - + uint256[] memory amounts = new uint256[](2); amounts[0] = amount0; amounts[1] = amount1; - + Fraction[] memory prices = adapter.price(pair, WETH, USDC, amounts); - + for (uint256 i = 0; i < prices.length; i++) { assertGt(prices[i].numerator, 0); assertGt(prices[i].denominator, 0); } } - - /// @dev Since TwapRelayer's calculateAmountOut function is internal, and using quoteSell would + + /// @dev Since TwapRelayer's calculateAmountOut function is internal, and + /// using quoteSell would /// revert the transaction if calculateAmountOut is not enough, - /// we need a threshold to cover this internal amount, applied to + /// we need a threshold to cover this internal amount, applied to function testSwapFuzzIntegral(uint256 specifiedAmount, bool isBuy) public { OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; - + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); uint256[] memory limits = new uint256[](2); uint256[] memory limitsMin = new uint256[](2); - + if (side == OrderSide.Buy) { limits = adapter.getLimits(pair, USDC, WETH); vm.assume(specifiedAmount < limits[1]); - + limitsMin = getMinLimits(USDC, WETH); vm.assume(specifiedAmount > limitsMin[1] * 115 / 100); - + deal(address(USDC), address(this), type(uint256).max); USDC.approve(address(adapter), type(uint256).max); } else { limits = adapter.getLimits(pair, USDC, WETH); vm.assume(specifiedAmount < limits[0]); - + limitsMin = getMinLimits(USDC, WETH); vm.assume(specifiedAmount > limitsMin[0] * 115 / 100); - + deal(address(USDC), address(this), type(uint256).max); USDC.approve(address(adapter), specifiedAmount); } - + uint256 usdc_balance_before = USDC.balanceOf(address(this)); uint256 weth_balance_before = WETH.balanceOf(address(this)); - - Trade memory trade = adapter.swap( - pair, - USDC, - WETH, - side, - specifiedAmount - ); - + + Trade memory trade = + adapter.swap(pair, USDC, WETH, side, specifiedAmount); + if (trade.calculatedAmount > 0) { if (side == OrderSide.Buy) { assertEq( specifiedAmount, WETH.balanceOf(address(this)) - weth_balance_before ); - + assertEq( trade.calculatedAmount, usdc_balance_before - USDC.balanceOf(address(this)) @@ -107,7 +101,7 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes { specifiedAmount, usdc_balance_before - USDC.balanceOf(address(this)) ); - + assertEq( trade.calculatedAmount, WETH.balanceOf(address(this)) - weth_balance_before @@ -127,76 +121,67 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes { function executeIncreasingSwapsIntegral(OrderSide side) internal { bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); - uint256 amountConstant_ = side == OrderSide.Sell ? 1000 * 10**6 : 10**17; - + uint256 amountConstant_ = + side == OrderSide.Sell ? 1000 * 10 ** 6 : 10 ** 17; + uint256[] memory amounts = new uint256[](TEST_ITERATIONS); amounts[0] = amountConstant_; for (uint256 i = 1; i < TEST_ITERATIONS; i++) { amounts[i] = amountConstant_ * i; } - + Trade[] memory trades = new Trade[](TEST_ITERATIONS); uint256 beforeSwap; for (uint256 i = 1; i < TEST_ITERATIONS; i++) { beforeSwap = vm.snapshot(); - + deal(address(USDC), address(this), amounts[i]); USDC.approve(address(adapter), amounts[i]); - + trades[i] = adapter.swap(pair, USDC, WETH, side, amounts[i]); vm.revertTo(beforeSwap); } - + for (uint256 i = 1; i < TEST_ITERATIONS - 1; i++) { - assertLe( - trades[i].calculatedAmount, - trades[i + 1].calculatedAmount - ); + assertLe(trades[i].calculatedAmount, trades[i + 1].calculatedAmount); assertLe(trades[i].gasUsed, trades[i + 1].gasUsed); assertEq(trades[i].price.compareFractions(trades[i + 1].price), 0); } } - - function testGetCapabilitiesIntegral( - bytes32 pair, - address t0, - address t1 - ) public { - Capability[] memory res = adapter.getCapabilities( - pair, - IERC20(t0), - IERC20(t1) - ); - + + function testGetCapabilitiesIntegral(bytes32 pair, address t0, address t1) + public + { + Capability[] memory res = + adapter.getCapabilities(pair, IERC20(t0), IERC20(t1)); + assertEq(res.length, 4); } - + function testGetTokensIntegral() public { bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); IERC20[] memory tokens = adapter.getTokens(pair); - + assertEq(tokens.length, 2); } - + function testGetLimitsIntegral() public { bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); uint256[] memory limits = adapter.getLimits(pair, USDC, WETH); - + assertEq(limits.length, 2); } - function getMinLimits(IERC20 sellToken, IERC20 buyToken) public view returns (uint256[] memory limits) { - ( - , - , - uint256 limitMin0, - , - uint256 limitMin1 - , - ) = relayer.getPoolState(address(sellToken), address(buyToken)); - + function getMinLimits(IERC20 sellToken, IERC20 buyToken) + public + view + returns (uint256[] memory limits) + { + (,, uint256 limitMin0,, uint256 limitMin1,) = + relayer.getPoolState(address(sellToken), address(buyToken)); + limits = new uint256[](2); limits[0] = limitMin0; limits[1] = limitMin1; } -} \ No newline at end of file +} diff --git a/evm/test/TemplateSwapAdapter.t.sol b/evm/test/TemplateSwapAdapter.t.sol index 8ace710..b0ac931 100644 --- a/evm/test/TemplateSwapAdapter.t.sol +++ b/evm/test/TemplateSwapAdapter.t.sol @@ -7,12 +7,14 @@ import "src/libraries/FractionMath.sol"; /// @title TemplateSwapAdapterTest /// @dev This is a template for a swap adapter test. -/// Test all functions that are implemented in your swap adapter, the two test included here are just an example. -/// Feel free to use UniswapV2SwapAdapterTest and BalancerV2SwapAdapterTest as a reference. +/// Test all functions that are implemented in your swap adapter, the two test +/// included here are just an example. +/// Feel free to use UniswapV2SwapAdapterTest and BalancerV2SwapAdapterTest as a +/// reference. contract TemplateSwapAdapterTest is Test, ISwapAdapterTypes { using FractionMath for Fraction; function testPriceFuzz(uint256 amount0, uint256 amount1) public {} function testSwapFuzz(uint256 specifiedAmount) public {} -} \ No newline at end of file +} diff --git a/evm/test/UniswapV2SwapAdapter.t.sol b/evm/test/UniswapV2SwapAdapter.t.sol index 960d0e1..b5a43fe 100644 --- a/evm/test/UniswapV2SwapAdapter.t.sol +++ b/evm/test/UniswapV2SwapAdapter.t.sol @@ -20,8 +20,8 @@ contract UniswapV2PairFunctionTest is Test, ISwapAdapterTypes { function setUp() public { uint256 forkBlock = 17000000; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); - adapter = new - UniswapV2SwapAdapter(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f); + adapter = + new UniswapV2SwapAdapter(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f); vm.label(address(adapter), "UniswapV2SwapAdapter"); vm.label(address(WETH), "WETH"); From 9b9146c23bbadbdb5bd889b02ff709fd74dbd568 Mon Sep 17 00:00:00 2001 From: pistomat Date: Wed, 27 Mar 2024 10:43:17 +0100 Subject: [PATCH 37/37] feat: add format check to evm CI --- .github/workflows/evm.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/evm.yml b/.github/workflows/evm.yml index c75f40d..bdd69a4 100644 --- a/.github/workflows/evm.yml +++ b/.github/workflows/evm.yml @@ -32,10 +32,16 @@ jobs: forge build --sizes id: build + - name: Run Forge format check + run: | + forge --version + forge fmt --check + id: format + - name: Run Forge tests run: | cd evm forge test -vvv id: test env: - ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }} + ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }} \ No newline at end of file