Learn Foundational Ethereum Topics with SQL
Many Ethereum tutorials target developers, but there’s a lack of educational resources for data analyst or for people who wish to see on-chain data without running a client or node.
This tutorial helps readers understand fundamental Ethereum concepts including transactions, blocks and gas by querying on-chain data with structured query language (SQL) through an interface provided by Dune Analytics(opens in a new tab).
On-chain data can help us understand Ethereum, the network, and as an economy for computing power and should serve as a base for understanding challenges facing Ethereum today (i.e., rising gas prices) and, more importantly, discussions around scaling solutions.
Transactions
A user’s journey on Ethereum starts with initializing a user-controlled account or an entity with an ETH balance. There are two account types - user-controlled or a smart contract (see ethereum.org).
Any account can be viewed on a block explorer like Etherscan(opens in a new tab). Block explorers are a portal to Ethereum’s data. They display, in real-time, data on blocks, transactions, miners, accounts and other on-chain activity (see here).
However, a user may wish to query the data directly to reconcile the information provided by external block explorers. Dune Analytics(opens in a new tab) provides this capability to anyone with some knowledge of SQL.
For reference, the smart contract account for the Ethereum Foundation (EF) can be viewed on Etherscan(opens in a new tab).
One thing to note is that all accounts, including the EF’s, has a public address that can be used to send and receive transactions.
The account balance on Etherscan comprises regular transactions and internal transactions. Internal transactions, despite the name, are not actual transactions that change the state of the chain. They are value transfers initiated by executing a contract (source(opens in a new tab)). Since internal transactions have no signature, they are not included on the blockchain and cannot be queried with Dune Analytics.
Therefore, this tutorial will focus on regular transactions. This can be queried as such:
1WITH temp_table AS (2SELECT3 hash,4 block_number,5 block_time,6 "from",7 "to",8 value / 1e18 AS ether,9 gas_used,10 gas_price / 1e9 AS gas_price_gwei11FROM ethereum."transactions"12WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'13ORDER BY block_time DESC14)15SELECT16 hash,17 block_number,18 block_time,19 "from",20 "to",21 ether,22 (gas_used * gas_price_gwei) / 1e9 AS txn_fee23FROM temp_table24إظهار الكل
This will yield the same information as provided on Etherscan's transaction page. For comparison, here are the two sources:
Etherscan
EF's contract page on Etherscan.(opens in a new tab)
Dune Analytics
You can find dashboard here(opens in a new tab). Click on the table to see the query (also see above).
Breaking Down Transactions
A submitted transaction includes several pieces of information including (source):
- Recipient: The receiving address (queried as "to")
- Signature: While a sender's private keys signs a transaction, what we can query with SQL is a sender's public address ("from").
- Value: This is the amount of ETH transferred (see
ether
column). - Data: This is arbitrary data that's been hashed (see
data
column) - gasLimit – the maximum amount of gas units that can be consumed by the transaction. Units of gas represent computational steps
- maxPriorityFeePerGas - the maximum amount of gas to be included as a tip to the miner
- maxFeePerGas - the maximum amount of gas willing to be paid for the transaction (inclusive of baseFeePerGas and maxPriorityFeePerGas)
We can query these specific pieces of information for transactions to the Ethereum Foundation public address:
1SELECT2 "to",3 "from",4 value / 1e18 AS ether,5 data,6 gas_limit,7 gas_price / 1e9 AS gas_price_gwei,8 gas_used,9 ROUND(((gas_used / gas_limit) * 100),2) AS gas_used_pct10FROM ethereum."transactions"11WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'12ORDER BY block_time DESC13إظهار الكل
Blocks
Each transaction will change the state of the Ethereum virtual machine (EVM) (source). Transactions are broadcasted to the network to be verified and included in a block. Each transaction is associated with a block number. To see the data, we could query a specific block number: 12396854 (the most recent block among Ethereum Foundation transactions as of this writing, 11/5/21).
Moreover, when we query the next two blocks, we can see that each block contains the hash of the previous block (i.e., parent hash), illustrating how the blockchain is formed.
Each block contains a reference to it parent block. This is shown below between the hash
and parent_hash
columns (source):
Here is the query(opens in a new tab) on Dune Analytics:
1SELECT2 time,3 number,4 hash,5 parent_hash,6 nonce7FROM ethereum."blocks"8WHERE "number" = 12396854 OR "number" = 12396855 OR "number" = 123968569LIMIT 1010إظهار الكل
We can examine a block by querying time, block number, difficulty, hash, parent hash, and nonce.
The only thing this query does not cover is list of transaction which requires a separate query below and state root. A full or archival node will store all transactions and state transitions, allowing for clients to query the state of the chain at any time. Because this requires large storage space, we can separate chain data from state data:
- Chain data (list of blocks, transactions)
- State data (result of each transaction’s state transition)
State root falls in the latter and is implicit data (not stored on-chain), while chain data is explicit and stored on the chain itself (source(opens in a new tab)).
For this tutorial, we'll be focusing on on-chain data that can be queried with SQL via Dune Analytics.
As stated above, each block contains a list of transactions, we can query this by filtering for a specific block. We'll try the most recent block, 12396854:
1SELECT * FROM ethereum."transactions"2WHERE block_number = 123968543ORDER BY block_time DESC`4
Here's the SQL output on Dune:
This single block being added to the chain changes the state of the Ethereum virtual machine (EVM). Dozens sometimes, hundreds of transactions are verified at once. In this specific case, 222 transactions were included.
To see how many were actually successful, we would add another filter to count successful transactions:
1WITH temp_table AS (2 SELECT * FROM ethereum."transactions"3 WHERE block_number = 12396854 AND success = true4 ORDER BY block_time DESC5)6SELECT7 COUNT(success) AS num_successful_txn8FROM temp_table9
For block 12396854, out of 222 total transactions, 204 were successfully verified: