diff --git a/blocks/evm/README.md b/blocks/evm/README.md index 2861e57..2a28c16 100644 --- a/blocks/evm/README.md +++ b/blocks/evm/README.md @@ -16,6 +16,7 @@ - [x] **Account Creation** - [x] **Gas Changes** - [x] **Nonce Changes** + - [x] **Creation Traces** ## Graph @@ -34,6 +35,7 @@ graph TD; extended --> account_creations; extended --> gas_changes; extended --> nonce_changes; + extended --> creation_traces; ``` ## Modules diff --git a/blocks/evm/src/account_creations.rs b/blocks/evm/src/account_creations.rs index 9268ef7..bacbd04 100644 --- a/blocks/evm/src/account_creations.rs +++ b/blocks/evm/src/account_creations.rs @@ -14,10 +14,16 @@ pub fn collect_account_creations(block: &Block, timestamp: &BlockTimestamp) -> V for call in &block.system_calls { for account_creation in &call.account_creations { account_creations.push(AccountCreation { + // block block_time: Some(timestamp.time), block_number: timestamp.number, block_hash: timestamp.hash.clone(), block_date: timestamp.date.clone(), + + // transaction + tx_hash: Some("".to_string()), + + // account creation account: bytes_to_hex(&account_creation.account), ordinal: account_creation.ordinal, }); @@ -29,10 +35,16 @@ pub fn collect_account_creations(block: &Block, timestamp: &BlockTimestamp) -> V for call in &transaction.calls { for account_creation in &call.account_creations { account_creations.push(AccountCreation { + // block block_time: Some(timestamp.time), block_number: timestamp.number, block_hash: timestamp.hash.clone(), block_date: timestamp.date.clone(), + + // transaction + tx_hash: Some(bytes_to_hex(&transaction.hash)), + + // account creation account: bytes_to_hex(&account_creation.account), ordinal: account_creation.ordinal, }); diff --git a/blocks/evm/src/balance_changes.rs b/blocks/evm/src/balance_changes.rs index 62b3ee8..ab45be4 100644 --- a/blocks/evm/src/balance_changes.rs +++ b/blocks/evm/src/balance_changes.rs @@ -43,10 +43,13 @@ pub fn collect_balance_changes(block: &Block, timestamp: &BlockTimestamp) -> Vec for balance_change in &call.balance_changes { let amount = optional_bigint_to_decimal(balance_change.new_value.clone()) - optional_bigint_to_decimal(balance_change.old_value.clone()); balance_changes.push(BalanceChange { + // block block_time: Some(timestamp.time), block_number: timestamp.number, block_hash: timestamp.hash.clone(), block_date: timestamp.date.clone(), + + // balance changes address: bytes_to_hex(&balance_change.address), new_balance: optional_bigint_to_string(&balance_change.new_value, "0"), old_balance: optional_bigint_to_string(&balance_change.old_value, "0"), @@ -64,10 +67,13 @@ pub fn collect_balance_changes(block: &Block, timestamp: &BlockTimestamp) -> Vec for balance_change in &call.balance_changes { let amount = optional_bigint_to_decimal(balance_change.new_value.clone()) - optional_bigint_to_decimal(balance_change.old_value.clone()); balance_changes.push(BalanceChange { + // block block_time: Some(timestamp.time), block_number: timestamp.number, block_hash: timestamp.hash.clone(), block_date: timestamp.date.clone(), + + // balance changes address: bytes_to_hex(&balance_change.address), new_balance: optional_bigint_to_string(&balance_change.new_value, "0"), old_balance: optional_bigint_to_string(&balance_change.old_value, "0"), diff --git a/blocks/evm/src/blocks.rs b/blocks/evm/src/blocks.rs index 0775cec..419534c 100644 --- a/blocks/evm/src/blocks.rs +++ b/blocks/evm/src/blocks.rs @@ -26,10 +26,13 @@ pub fn collect_block(block: &Block, timestamp: &BlockTimestamp) -> BlockHeader { let total_withdrawals = block.balance_changes.iter().filter(|t| t.reason == 16).count() as u64; BlockHeader { + // clock time: Some(timestamp.time), number: header.number, date: timestamp.date.clone(), hash: bytes_to_hex(&block.hash), + + // header parent_hash: bytes_to_hex(&header.parent_hash), nonce: header.nonce, ommers_hash: bytes_to_hex(&header.uncle_hash), @@ -50,6 +53,8 @@ pub fn collect_block(block: &Block, timestamp: &BlockTimestamp) -> BlockHeader { base_fee_per_gas: optional_bigint_to_string(&header.base_fee_per_gas, ""), blob_gas_used: optional_u64_to_string(&header.blob_gas_used, ""), excess_blob_gas: optional_u64_to_string(&header.excess_blob_gas, ""), + + // counters size: block.size, total_transactions: block.transaction_traces.len() as u64, successful_transactions, diff --git a/blocks/evm/src/code_changes.rs b/blocks/evm/src/code_changes.rs index 733898f..f8ff278 100644 --- a/blocks/evm/src/code_changes.rs +++ b/blocks/evm/src/code_changes.rs @@ -13,10 +13,13 @@ pub fn collect_code_changes(block: &Block, timestamp: &BlockTimestamp) -> Vec Vec Vec { + let mut creation_traces: Vec = vec![]; + + // Collect code changes from system calls + for trace in block.transaction_traces.iter() { + for call in trace.calls.iter() { + if call.call_type() == CallType::Create { + for code in call.code_changes.iter() { + let factory = if trace.to == code.address { "".to_string() } else { bytes_to_hex(&trace.to) }; + + creation_traces.push(CreationTrace { + // block + block_time: Some(timestamp.time), + block_number: timestamp.number, + block_hash: timestamp.hash.clone(), + block_date: timestamp.date.clone(), + + // creation trace + from: bytes_to_hex(&trace.from), + tx_hash: bytes_to_hex(&trace.hash), + address: bytes_to_hex(&code.address), + factory: factory.to_string(), + code: bytes_to_hex(&code.new_code), + }); + } + } + } + } + + creation_traces +} diff --git a/blocks/evm/src/events.rs b/blocks/evm/src/events.rs index c584c9f..80580c2 100644 --- a/blocks/evm/src/events.rs +++ b/blocks/evm/src/events.rs @@ -8,6 +8,7 @@ use crate::account_creations::collect_account_creations; use crate::balance_changes::collect_balance_changes; use crate::blocks::{block_detail_to_string, collect_block}; use crate::code_changes::collect_code_changes; +use crate::creation_traces::collect_creation_traces; use crate::gas_changes::collect_gas_changes; use crate::logs::collect_logs; use crate::nonce_changes::collect_nonce_changes; @@ -32,5 +33,6 @@ pub fn map_events(clock: Clock, block: Block) -> Result { account_creations: collect_account_creations(&block, ×tamp), nonce_changes: collect_nonce_changes(&block, ×tamp), gas_changes: collect_gas_changes(&block, ×tamp), + creation_traces: collect_creation_traces(&block, ×tamp), }) } diff --git a/blocks/evm/src/lib.rs b/blocks/evm/src/lib.rs index a35207e..99967b6 100644 --- a/blocks/evm/src/lib.rs +++ b/blocks/evm/src/lib.rs @@ -2,6 +2,7 @@ mod account_creations; mod balance_changes; mod blocks; mod code_changes; +mod creation_traces; mod events; mod gas_changes; mod logs; diff --git a/blocks/evm/src/logs.rs b/blocks/evm/src/logs.rs index 2f42414..c475109 100644 --- a/blocks/evm/src/logs.rs +++ b/blocks/evm/src/logs.rs @@ -34,9 +34,9 @@ pub fn collect_logs(block: &Block, timestamp: &BlockTimestamp, detail_level: &st block_index: log.block_index, contract_address: bytes_to_hex(&log.address), topic0: extract_topic(&log.topics, 0), - topic1: extract_topic(&log.topics, 1), - topic2: extract_topic(&log.topics, 2), - topic3: extract_topic(&log.topics, 3), + topic1: Some(extract_topic(&log.topics, 1)), + topic2: Some(extract_topic(&log.topics, 2)), + topic3: Some(extract_topic(&log.topics, 3)), data: bytes_to_hex(&log.data), }); } diff --git a/blocks/evm/src/pb/evm.rs b/blocks/evm/src/pb/evm.rs index b337562..cca45a3 100644 --- a/blocks/evm/src/pb/evm.rs +++ b/blocks/evm/src/pb/evm.rs @@ -23,6 +23,8 @@ pub struct Events { pub nonce_changes: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag="10")] pub gas_changes: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="11")] + pub creation_traces: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -389,11 +391,12 @@ pub struct AccountCreation { #[prost(string, tag="4")] pub block_date: ::prost::alloc::string::String, /// -- account creation -- - /// + #[prost(string, optional, tag="5")] + pub tx_hash: ::core::option::Option<::prost::alloc::string::String>, /// block global ordinal - #[prost(uint64, tag="5")] + #[prost(uint64, tag="6")] pub ordinal: u64, - #[prost(string, tag="6")] + #[prost(string, tag="7")] pub account: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] @@ -446,4 +449,28 @@ pub struct GasChange { #[prost(uint32, tag="9")] pub reason_code: u32, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreationTrace { + /// -- block -- + #[prost(message, optional, tag="1")] + pub block_time: ::core::option::Option<::prost_types::Timestamp>, + #[prost(uint64, tag="2")] + pub block_number: u64, + #[prost(string, tag="3")] + pub block_hash: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub block_date: ::prost::alloc::string::String, + /// -- creation trace -- + #[prost(string, tag="5")] + pub tx_hash: ::prost::alloc::string::String, + #[prost(string, tag="6")] + pub address: ::prost::alloc::string::String, + #[prost(string, tag="7")] + pub from: ::prost::alloc::string::String, + #[prost(string, tag="8")] + pub factory: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub code: ::prost::alloc::string::String, +} // @@protoc_insertion_point(module) diff --git a/docs/google_big_query.md b/docs/google_big_query.md new file mode 100644 index 0000000..b4428e7 --- /dev/null +++ b/docs/google_big_query.md @@ -0,0 +1,5 @@ +## Google Big Query + + + + diff --git a/proto/evm.proto b/proto/evm.proto index 5a592a2..274988b 100644 --- a/proto/evm.proto +++ b/proto/evm.proto @@ -16,9 +16,9 @@ message Events { repeated AccountCreation account_creations = 8; repeated NonceChange nonce_changes = 9; repeated GasChange gas_changes = 10; + repeated CreationTrace creation_traces = 11; } - message Block { // -- clock -- google.protobuf.Timestamp time = 1; @@ -37,8 +37,8 @@ message Block { string withdrawals_root = 12; // EVM Root EIP-4895 (Shangai Fork) string parent_beacon_root = 13; // EVM Root EIP-4788 (Dencun Fork) string miner = 14; - uint64 difficulty = 15 [(parquet.column) = {type: UINT256}]; - string total_difficulty = 16; + uint64 difficulty = 15; + string total_difficulty = 16 [(parquet.column) = {type: UINT256}]; string mix_hash = 17; string extra_data = 18; string extra_data_utf8 = 19; @@ -226,9 +226,12 @@ message AccountCreation { string block_hash = 3; string block_date = 4; + // -- transaction -- + optional string tx_hash = 5; + // -- account creation -- - uint64 ordinal = 5; // block global ordinal - string account = 6; + uint64 ordinal = 6; // block global ordinal + string account = 7; } message NonceChange { @@ -259,3 +262,20 @@ message GasChange { string reason = 8; uint32 reason_code = 9; } + +message CreationTrace { + // -- block -- + google.protobuf.Timestamp block_time = 1; + uint64 block_number = 2; + string block_hash = 3; + string block_date = 4; + + // -- transaction -- + string tx_hash = 5; + + // -- creation trace -- + string address = 6; + string from = 7; + string factory = 8; + string code = 9; +} \ No newline at end of file diff --git a/snowflake/ethereum/README.md b/snowflake/ethereum/README.md index 1911a67..8780510 100644 --- a/snowflake/ethereum/README.md +++ b/snowflake/ethereum/README.md @@ -14,6 +14,7 @@ Try 30 day limited trial access to the dataset on the [Snowflake Data Marketplac | `logs` | Event logs from smart contracts. | | `storage_changes` | Changes in smart contract storage. | | `code_changes` | Smart contract code updates. | +| `creation_traces` | Contract creation transactions. | ## Sample SQL Queries