Chapter 1
Introduction to Ethereum & Key Differences from Bitcoin
Ethereum is a decentralized computing platform that extends Bitcoin’s blockchain concept beyond peer-to-peer transactions. While Bitcoin was designed as a secure digital currency, Ethereum was created to support smart contracts and decentralized applications (dApps).
This chapter explores how Ethereum differs from Bitcoin in philosophy and technical architecture, highlighting its role in decentralized finance (DeFi), tokenization, and programmability.
Ethereum Origins: The Vision of a “World Computer”
Vitalik Buterin’s Motivation
Ethereum was proposed by Vitalik Buterin in 2013 to address Bitcoin’s limited programmability. While Bitcoin only allows basic scripting for transactions, Ethereum provides a Turing-complete environment, enabling complex smart contracts and dApps.
Ethereum’s vision is to be a “World Computer”—a decentralized platform where applications execute code without intermediaries.
Key Advancements Over Bitcoin
- Beyond Digital Currency – Ethereum enables smart contracts, DeFi, and NFTs instead of just financial transactions.
- Programmability – Ethereum supports complex scripts, allowing decentralized applications to function without centralized control.
- Stateful Accounts – Ethereum uses an account-based model, making transactions more flexible than Bitcoin’s UTXO model.
Bitcoin vs. Ethereum: Key Architectural Differences
Bitcoin and Ethereum both use blockchains but differ in how transactions and accounts are structured.
Comparison Table
Feature | Bitcoin | Ethereum |
---|---|---|
Primary Use Case | Digital currency | Smart contracts and dApps |
Consensus Mechanism | Proof of Work (PoW) → Proof of Stake (PoS) | Proof of Stake (PoS) |
Transaction Model | UTXO (Unspent Transaction Output) | Account-based |
Block Time | ~10 minutes | ~12-15 seconds |
Native Currency | BTC | ETH |
Smart Contracts | Limited scripting | Fully programmable (Solidity) |
UTXO vs. Account-Based Model
Ethereum uses an account-based model, while Bitcoin follows a UTXO model.
Bitcoin’s UTXO Model
Each transaction spends unspent outputs from previous transactions, ensuring better security and privacy.
Example UTXO Transaction:
<pre><code class=”language-js”> Input: 0.8 BTC (from previous transaction) Output: 0.5 BTC (to recipient), 0.3 BTC (change back to sender) </code></pre>
Ethereum’s Account-Based Model
Ethereum updates account balances directly, making smart contract interactions possible.
Example Ethereum Transaction:
<pre><code class=”language-js”> Sender Balance: 10 ETH Transaction: -2 ETH to recipient New Sender Balance: 8 ETH </code></pre>
Model | Advantages | Disadvantages |
---|---|---|
UTXO | Enhanced privacy, parallel processing | More complex tracking |
Account-Based | Simpler, allows smart contracts | Higher risk of replay attacks |
Core Use Cases: Ethereum Beyond Digital Currency
Ethereum extends blockchain functionality far beyond payments.
Smart Contracts: Self-Executing Code on the Blockchain
A smart contract is a programmable contract that runs on Ethereum’s blockchain, eliminating intermediaries.
Example Smart Contract (Solidity):
<pre><code class=”language-js”> pragma solidity ^0.8.0; contract SimpleContract { uint public value; function setValue(uint _value) public { value = _value; } } </code></pre>
Smart contracts enable trustless transactions, automating agreements without banks or brokers. Once deployed, they are immutable and tamper-proof.
ERC-20 Tokens: The Standard for Digital Assets
Ethereum introduced token standards that power thousands of cryptocurrencies and DeFi applications.
ERC-20 is the most widely used token standard for fungible tokens (interchangeable assets like USDC, DAI).
Example ERC-20 Token Contract:
<pre><code class=”language-js”> pragma solidity ^0.8.0; import “@openzeppelin/contracts/token/ERC20/ERC20.sol”; contract MyToken is ERC20 { constructor() ERC20(“MyToken”, “MTK”) { _mint(msg.sender, 1000000 * (10 ** uint256(decimals()))); } } </code></pre>
Use Cases of ERC-20 Tokens:
- Stablecoins (e.g., USDT, USDC)
- Governance tokens for DAOs (Decentralized Autonomous Organizations)
- Liquidity provider tokens in decentralized exchanges (DEXs)
Decentralized Finance (DeFi): The Future of Banking
Ethereum enables DeFi applications, removing the need for traditional financial intermediaries.
DeFi Application | Function | Example Protocols |
---|---|---|
Decentralized Exchanges (DEXs) | Peer-to-peer trading | Uniswap, SushiSwap |
Lending & Borrowing | Collateralized loans | Aave, Compound |
Yield Farming | Earning rewards for providing liquidity | Yearn Finance |
Example of interacting with a DeFi smart contract:
<pre><code class=”language-js”> contract DeFiLending { mapping(address => uint) public balances; function deposit() public payable { balances[msg.sender] += msg.value; } } </code></pre>
DeFi applications run without banks, enabling anyone to lend, borrow, and trade without KYC (Know Your Customer) restrictions.
Ethereum’s Transition to Proof of Stake (PoS)
Ethereum originally used Proof of Work (PoW) like Bitcoin but transitioned to Proof of Stake (PoS) with Ethereum 2.0 (The Merge).
How PoS Improves Ethereum
Consensus Mechanism | Bitcoin (PoW) | Ethereum (PoS) |
---|---|---|
Energy Consumption | High | Low |
Block Creation Time | 10 minutes | ~12 seconds |
Security Model | Miners solve cryptographic puzzles | Validators stake ETH |
Instead of mining with hardware, Ethereum validators stake ETH to secure the network.
To stake ETH and become a validator:
<pre><code class=”language-js”> eth2 deposit –amount 32 –validator myValidator </code></pre>
This transition reduces energy usage by 99% and makes Ethereum more scalable and environmentally friendly.
Future Developments in Ethereum
Ethereum continues to evolve, with major upgrades improving scalability, privacy, and transaction efficiency.
Upcoming Upgrade | Expected Benefit |
---|---|
Sharding | Splits blockchain into smaller parts to improve speed. |
Layer 2 Solutions (Optimistic & ZK Rollups) | Reduces fees and increases transaction throughput. |
Account Abstraction | Enhances wallet security and user experience. |
Example: Optimistic Rollups batch multiple transactions, reducing fees and increasing efficiency:
<pre><code class=”language-js”> batchProcessTransactions(transactions); </code></pre>
Layer 2 solutions will allow Ethereum to handle thousands of transactions per second (TPS), rivaling traditional financial systems.
Conclusion
Ethereum expands upon Bitcoin’s foundation by introducing smart contracts, DeFi, and decentralized applications.
- Ethereum is programmable, supporting DeFi, NFTs, and smart contracts.
- Ethereum uses an account-based model, while Bitcoin follows the UTXO model.
- Ethereum transitioned to Proof of Stake, making it energy-efficient and scalable.
With continued improvements in scalability, security, and functionality, Ethereum remains the dominant blockchain for decentralized applications and financial innovation.
Key Concepts
Bitcoin and Ethereum use different transaction models to track balances and process transactions. Bitcoin follows the Unspent Transaction Output (UTXO) model, while Ethereum adopts an account-based model similar to traditional banking.
This chapter explores how these models work, their advantages and disadvantages, and how they impact transaction efficiency, privacy, and scalability.
Bitcoin’s UTXO Model: Tracking Unspent Outputs
How the UTXO Model Works
In Bitcoin, every transaction consumes previous outputs (UTXOs) and creates new ones. Instead of accounts, Bitcoin maintains a ledger of individual unspent outputs, ensuring every coin has a clear origin.
Each transaction consists of:
- Inputs (UTXOs being spent)
- Outputs (new UTXOs created)
A Bitcoin wallet does not store a balance; instead, it tracks a collection of UTXOs controlled by the user's private key.
Example: Bitcoin UTXO Transaction
A user has two UTXOs:
- 0.3 BTC from Bob
- 0.7 BTC from Alice
They send 0.5 BTC to Dave.
<pre><code class="language-js"> Inputs: - 0.3 BTC (Bob) - 0.7 BTC (Alice) Outputs: - 0.5 BTC (to Dave) - 0.499 BTC (back to sender as change) - 0.001 BTC (transaction fee) </code></pre>
Since UTXOs must be spent in full, the sender receives the excess balance as a new UTXO (change output).
Ethereum’s Account-Based Model: Balances Instead of UTXOs
How the Account-Based Model Works
Ethereum transactions update account balances directly, similar to a bank ledger. Instead of tracking individual unspent outputs, Ethereum keeps a state of all account balances in the blockchain.
Each account has:
- A balance of ETH.
- Storage for smart contract states.
- Nonce (transaction counter to prevent replay attacks).
Example: Ethereum Transaction
Alice has 10 ETH and sends 2 ETH to Bob.
<pre><code class="language-js"> Sender Balance: 10 ETH Transaction: -2 ETH to Bob New Sender Balance: 8 ETH New Receiver Balance: 2 ETH </code></pre>
The Ethereum network modifies the balances directly, without needing separate outputs for change like Bitcoin.
Key Differences Between UTXO and Account-Based Models
Feature | Bitcoin (UTXO Model) | Ethereum (Account Model) |
---|---|---|
Tracking Funds | Uses unspent transaction outputs | Uses account balances |
Transaction Type | Each transaction spends specific UTXOs | Each transaction modifies balances directly |
Change Handling | Requires a change output if spending more than required | No change needed; balance updates directly |
Privacy | Better privacy; transactions can’t be linked easily | Lower privacy; account balances are publicly visible |
Smart Contracts | Limited scripting, mainly for transactions | Fully programmable smart contracts |
Scalability | Harder to scale due to complex UTXO tracking | Easier to scale, but more vulnerable to spam attacks |
Advantages & Disadvantages of Each Model
Bitcoin UTXO Model: Pros and Cons
✅ Improved Privacy – Transactions are more difficult to link because new UTXOs are created.
✅ Better Parallel Processing – Nodes can verify multiple UTXOs in parallel, making validation more efficient.
❌ More Complex Transactions – Requires change outputs, making wallets more complex to manage.
❌ Higher Storage Requirements – UTXO sets grow over time, requiring more storage.
Ethereum Account Model: Pros and Cons
✅ Simpler Transactions – No need for change outputs, making transactions easier to construct.
✅ More Efficient for Smart Contracts – Account balances simplify smart contract interactions.
❌ Less Privacy – Account balances are always visible, making transaction tracing easier.
❌ Higher Risk of Replay Attacks – Transactions can be replayed on different chains if not properly handled.
Security Implications of UTXO vs. Account Models
1. Preventing Double-Spending
Both Bitcoin and Ethereum prevent double-spending but use different methods:
- Bitcoin checks if UTXOs are already spent before confirming a transaction.
- Ethereum uses a nonce system, ensuring transactions are processed in order.
Example: Ethereum uses nonces to track transactions.
If Alice sends two transactions at the same time, the network ensures they execute in sequence:
<pre><code class="language-js"> Transaction 1: Nonce 5 → Valid Transaction 2: Nonce 4 → Rejected (out of order) </code></pre>
2. Reducing Blockchain Bloat
Ethereum’s account model requires less storage than Bitcoin’s UTXO model, as it does not need to track every unspent output.
- Bitcoin nodes store all UTXOs, making the blockchain larger over time.
- Ethereum nodes only store account states, reducing storage needs.
Example: To verify Bitcoin transactions, a node must scan the entire UTXO set:
<pre><code class="language-js"> if (utxo_is_spent(transaction_input)) { reject_transaction(); } </code></pre>
For Ethereum, verifying a balance is simpler:
<pre><code class="language-js"> if (sender_balance >= transaction_amount) { execute_transaction(); } </code></pre>
How the Two Models Affect Smart Contracts and DeFi
Ethereum’s account model enables smart contracts, while Bitcoin’s UTXO model limits programmability.
1. Smart Contracts Require an Account-Based Model
Ethereum smart contracts interact with accounts, modifying balances directly.
Example: A DeFi lending smart contract modifies the sender’s balance:
<pre><code class="language-js"> contract Lending { mapping(address => uint) public deposits; function deposit() public payable { deposits[msg.sender] += msg.value; } } </code></pre>
2. Bitcoin’s UTXO Model Limits Smart Contracts
Bitcoin uses Script, a limited scripting language without loops or complex logic.
Example: A Bitcoin multi-signature script:
<pre><code class="language-js"> OP_2 <public_key_1> <public_key_2> <public_key_3> OP_3 OP_CHECKMULTISIG </code></pre>
This script allows 2 of 3 parties to approve transactions but does not support advanced logic like Ethereum’s DeFi contracts.
Future Developments in Ethereum and Bitcoin Models
1. Ethereum Upgrades (Scalability & Security)
Ethereum plans to improve its account model with Layer 2 scaling and sharding.
- Sharding will split Ethereum into multiple chains, reducing congestion.
- Layer 2 solutions (Rollups) will batch transactions, lowering gas fees.
Example: Optimistic Rollups reduce fees by processing transactions off-chain:
<pre><code class="language-js"> batchProcessTransactions(transactions); </code></pre>
2. Bitcoin’s Future Smart Contract Enhancements
Bitcoin is integrating Taproot, which enhances privacy and smart contract flexibility.
- Taproot makes multi-signature transactions indistinguishable from regular transactions.
- Bitcoin’s Layer 2 networks (Lightning Network) improve scalability.
Conclusion
Ethereum’s account-based model and Bitcoin’s UTXO model serve different purposes, each with trade-offs in scalability, security, and programmability.
- Bitcoin’s UTXO model enhances privacy and security, making it ideal for peer-to-peer transactions.
- Ethereum’s account model enables smart contracts and decentralized applications, powering DeFi, NFTs, and DAOs.
- Future upgrades in Ethereum’s sharding and Bitcoin’s Taproot will continue improving both models for better scalability and efficiency.
Understanding these models is crucial for developers and users who want to interact with blockchain networks efficiently and securely.
Smart contracts are self-executing programs stored on the Ethereum blockchain that automatically enforce agreements without intermediaries. They power decentralized applications (dApps), enabling use cases like Decentralized Finance (DeFi), Non-Fungible Tokens (NFTs), and DAOs (Decentralized Autonomous Organizations).
This chapter explores how smart contracts work, their benefits, and how they enable decentralized applications on Ethereum.
What Are Smart Contracts?
Definition
A smart contract is a programmable contract that runs on Ethereum’s blockchain, executing transactions automatically when predefined conditions are met.
Key Features of Smart Contracts
- Trustless Execution – No need for intermediaries like banks or lawyers.
- Immutable & Transparent – Once deployed, smart contracts cannot be altered and are publicly viewable.
- Automated Transactions – When conditions are met, the contract executes automatically.
Example: A Simple Smart Contract in Solidity
Solidity is Ethereum’s programming language for writing smart contracts.
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleContract { uint public value; function setValue(uint _value) public { value = _value; } } </code></pre>
setValue()
updates the storedvalue
on the blockchain.- The transaction is recorded on Ethereum, ensuring decentralization and immutability.
How Smart Contracts Work on Ethereum
1. Deployment
Smart contracts are deployed to Ethereum via transactions. Once deployed, they receive a unique contract address and remain permanently on the blockchain.
2. Execution
Users interact with smart contracts by sending transactions.
- Transactions trigger functions inside the contract, modifying state or transferring assets.
Example of calling a function:
<pre><code class="language-js"> contract.storeValue(100); </code></pre>
3. Gas Fees
Executing a smart contract requires gas fees to compensate Ethereum validators for processing transactions.
- More complex operations require higher gas fees.
To estimate gas costs before execution:
<pre><code class="language-js"> eth.estimateGas({ to: contractAddress, data: contractFunction }); </code></pre>
How Smart Contracts Enable Decentralized Applications (dApps)
Ethereum’s smart contract ecosystem supports a wide range of decentralized applications (dApps).
dApp Type | Function | Example Protocols |
---|---|---|
Decentralized Finance (DeFi) | Lending, trading, yield farming | Uniswap, Aave, Compound |
Non-Fungible Tokens (NFTs) | Digital asset ownership | OpenSea, Rarible, Axie Infinity |
Gaming & Metaverse | Blockchain-based games | Decentraland, The Sandbox |
DAOs (Decentralized Autonomous Organizations) | Community governance | MakerDAO, Aragon |
Key Ethereum Standards for Smart Contracts
Ethereum uses token standards to ensure compatibility between smart contracts and dApps.
ERC-20: The Standard for Fungible Tokens
ERC-20 defines rules for creating fungible tokens (tokens that are interchangeable, like USDT or DAI).
Example ERC-20 Token Contract:
<pre><code class="language-js"> pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract MyToken is ERC20 { constructor() ERC20("MyToken", "MTK") { _mint(msg.sender, 1000000 * (10 ** uint256(decimals()))); } } </code></pre>
This contract:
- Creates a fungible token named MyToken (MTK).
- Mints 1,000,000 tokens to the deployer’s address.
ERC-721: The Standard for NFTs
ERC-721 is used for non-fungible tokens (NFTs), ensuring each token is unique.
Example ERC-721 Contract:
<pre><code class="language-js"> pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract MyNFT is ERC721 { constructor() ERC721("MyNFT", "NFT") { _mint(msg.sender, 1); } } </code></pre>
This contract:
- Creates an NFT collection called MyNFT.
- Mints one unique NFT to the deployer’s wallet.
NFTs enable digital art, in-game assets, and metaverse properties to exist on-chain.
DeFi and Smart Contracts: The Foundation of Decentralized Finance
Decentralized Exchanges (DEXs)
DEXs allow users to trade tokens without intermediaries, using smart contracts to manage liquidity pools.
Example of providing liquidity to Uniswap using a smart contract:
<pre><code class="language-js"> interface IUniswap { function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable; } </code></pre>
Lending & Borrowing Platforms
Users can lend assets and earn interest using smart contracts.
Example: Depositing ETH into Aave’s Lending Pool
<pre><code class="language-js"> ILendingPool aave = ILendingPool(0x3df...); aave.deposit{value: 1 ether}(address(0), msg.sender, 0); </code></pre>
These smart contracts eliminate banks, allowing users to borrow, lend, and trade trustlessly.
Security Considerations for Smart Contracts
Smart contracts are immutable, meaning bugs and vulnerabilities cannot be changed once deployed.
Common Smart Contract Risks
Risk | Description | Example Exploits |
---|---|---|
Reentrancy Attacks | Repeated external calls drain funds. | The DAO Hack (2016) |
Integer Overflow | Large numbers break contract logic. | Smart contract errors in early ERC-20 tokens. |
Front-Running | Attackers manipulate pending transactions. | MEV (Miner Extractable Value) exploits. |
Best Practices for Secure Smart Contracts
- Use Secure Libraries – Use OpenZeppelin’s audited contracts.
- Implement Reentrancy Guards – Prevent multiple function calls.
Example of a reentrancy-safe contract:
<pre><code class="language-js"> contract SecureContract { bool private locked; modifier noReentrant() { require(!locked, "No reentrancy allowed"); locked = true; _; locked = false; } function withdraw() public noReentrant { // Secure withdrawal logic } } </code></pre>
The Future of Smart Contracts on Ethereum
Ethereum’s smart contracts are evolving with Layer 2 scaling, security improvements, and new token standards.
Upgrade | Impact |
---|---|
Layer 2 Rollups (Optimistic & ZK Rollups) | Faster transactions, lower fees |
Account Abstraction | Simplifies smart contract wallets |
EIP-1559 | Improves gas fee predictability |
Ethereum is also transitioning to Sharding, which will divide the blockchain into smaller chains, significantly improving scalability and efficiency.
Example of Optimistic Rollups batching multiple transactions:
<pre><code class="language-js"> batchProcessTransactions(transactions); </code></pre>
These advancements ensure Ethereum remains the leading platform for decentralized applications.
Conclusion
Smart contracts are the backbone of Ethereum’s decentralized ecosystem, enabling:
- Trustless automation through immutable and transparent code.
- DeFi, NFTs, and DAOs, removing intermediaries and increasing financial accessibility.
- Secure, efficient applications built on Ethereum’s blockchain.
With continued improvements in scalability, security, and developer tools, Ethereum’s smart contracts will power the next generation of blockchain applications, shaping the future of decentralized finance and digital ownership.
Ethereum originally operated under a Proof of Work (PoW) consensus mechanism, similar to Bitcoin, requiring miners to solve complex mathematical problems to validate transactions and secure the network. However, this method was energy-intensive, slow, and limited in scalability.
With Ethereum 2.0 (The Merge), Ethereum transitioned to Proof of Stake (PoS), a more efficient, scalable, and secure consensus mechanism that eliminates mining and instead uses validators who stake ETH to secure the network.
This chapter explores how Ethereum’s transition to PoS improves scalability, reduces energy consumption, enhances security, and prepares the network for future upgrades.
Proof of Work vs. Proof of Stake: Key Differences
Ethereum’s transition to Proof of Stake (PoS) replaced the energy-intensive mining process of Proof of Work (PoW) with a staking-based system that is faster, more decentralized, and environmentally friendly.
Comparison Table: PoW vs. PoS
Feature | Proof of Work (PoW) | Proof of Stake (PoS) |
---|---|---|
Validation Method | Mining (solving cryptographic puzzles) | Staking ETH and validating transactions |
Energy Consumption | Very high (relies on computational power) | 99.95% lower than PoW |
Block Creation Time | ~12–14 seconds | ~12 seconds |
Security Model | High cost to attack due to hardware requirements | Slashing penalties prevent malicious behavior |
Scalability | Limited transactions per second (TPS) | More efficient, preparing for sharding |
Scalability Improvements with Proof of Stake
Ethereum’s transition to PoS lays the foundation for future scalability solutions like Sharding and Layer 2 solutions, making Ethereum capable of processing thousands of transactions per second (TPS).
A. Faster Transaction Finality
Finality is the point where a transaction cannot be reversed. In PoS, Ethereum achieves finality faster because validators confirm blocks more efficiently.
Example:
In PoW, a transaction needs multiple confirmations (~12 minutes for finality). In PoS, finality is reached within a few minutes due to validator attestations.
B. Reduction in Network Congestion
Ethereum’s PoS mechanism allows transactions to be validated faster, leading to lower gas fees and higher throughput.
Before PoS, Ethereum could handle ~15 transactions per second (TPS). With PoS and upcoming sharding, Ethereum aims for 100,000 TPS.
C. Sharding: The Next Step in Scaling
PoS enables Sharding, which will further increase Ethereum’s scalability.
- The Ethereum blockchain will be split into multiple parallel chains (shards).
- Validators process only a portion of transactions, reducing network congestion.
- Combined with Layer 2 rollups, Ethereum will handle massive transaction volumes at lower fees.
Example:
If Ethereum’s single-chain PoW system could handle 15 TPS, then Sharding + PoS could scale this to 100,000 TPS by distributing transactions across multiple shards.
Security Enhancements in Proof of Stake
PoS provides stronger security guarantees than PoW by incentivizing honest behavior and punishing malicious actors.
A. Slashing: Economic Security Against Attacks
Validators must stake ETH (minimum 32 ETH) to participate in PoS. If a validator attempts to attack the network, their staked ETH is slashed (destroyed).
Example:
If a validator intentionally confirms fraudulent transactions, part of their 32 ETH stake is burned, discouraging dishonest activity.
B. Lower Risk of 51% Attacks
A 51% attack occurs when an entity controls most of the network’s computing power, allowing them to reorganize blocks and manipulate transactions.
- In PoW, an attacker needs 51% of mining power, requiring billions of dollars in hardware and electricity.
- In PoS, an attacker would need 51% of all staked ETH, making an attack financially infeasible.
C. Decentralization and Validator Participation
- PoS lowers the entry barrier for network participation, encouraging more validators to join.
- Unlike PoW, where mining power is concentrated in a few large mining pools, PoS allows anyone with 32 ETH to validate transactions, improving network decentralization.
Energy Efficiency: Reducing Ethereum’s Environmental Impact
Ethereum’s transition to PoS reduced energy consumption by over 99.95%, making it significantly more sustainable than PoW-based networks.
Network | Annual Energy Consumption |
---|---|
Bitcoin (PoW) | ~85 TWh (similar to the entire country of Belgium) |
Ethereum (Pre-PoS) | ~23 TWh |
Ethereum (PoS) | ~0.0026 TWh (99.95% reduction) |
By eliminating high-powered mining rigs, Ethereum PoS makes the network sustainable, scalable, and cost-efficient.
How to Stake Ethereum and Participate in PoS
To become a validator, users must stake 32 ETH and run an Ethereum node.
A. Setting Up an Ethereum Validator
Deposit 32 ETH into the staking contract:
<pre><code class="language-js"> eth2 deposit --amount 32 --validator myValidator </code></pre>
Run a Validator Node to process transactions:
<pre><code class="language-js"> geth --syncmode "full" --network "mainnet" --validator </code></pre>
Earn Rewards for securing the network:
Validators receive staking rewards in ETH for attesting and proposing blocks.
If a validator behaves maliciously, part of their stake is slashed.
For those with less than 32 ETH, staking can be done via staking pools (e.g., Lido, Rocket Pool) or exchanges offering staking services.
Impact of Ethereum’s PoS Upgrade on Users and Developers
Ethereum’s PoS upgrade enhances usability, reduces transaction fees, and improves developer experience.
A. Lower Gas Fees for Users
By increasing transaction efficiency, Ethereum reduces gas fees, making DeFi, NFTs, and dApps more accessible.
B. Faster Transactions
Blocks are produced every 12 seconds, improving transaction confirmation times compared to Bitcoin’s 10-minute block time.
C. Developer Benefits
- PoS reduces the complexity of running a node, allowing more developers to contribute to Ethereum.
- Smart contracts execute faster due to the improved consensus mechanism.
- Ethereum remains decentralized, ensuring dApps and financial applications remain trustless and censorship-resistant.
Future of Ethereum Post-PoS
With PoS successfully implemented, Ethereum is now preparing for the next phase of upgrades, including Sharding, Layer 2 scaling, and further security enhancements.
Upcoming Upgrade | Expected Benefit |
---|---|
Sharding | Splits blockchain into smaller parts to improve transaction speed. |
Layer 2 Rollups (Optimistic & ZK Rollups) | Reduces gas fees and improves transaction throughput. |
Account Abstraction | Enhances wallet security and usability. |
Example:
Optimistic Rollups batch multiple transactions, reducing fees and increasing efficiency:
<pre><code class="language-js"> batchProcessTransactions(transactions); </code></pre>
These advancements will allow Ethereum to handle thousands of transactions per second (TPS), making it the most scalable and efficient smart contract platform.
Conclusion
Ethereum’s transition to Proof of Stake improves scalability, security, and sustainability by:
- Eliminating mining, reducing energy consumption by 99.95%.
- Increasing network efficiency, allowing Ethereum to scale to 100,000 TPS with Sharding and Layer 2 solutions.
- Enhancing security, making 51% attacks financially impractical.
With PoS now live, Ethereum continues to evolve, providing faster, cheaper, and more secure transactions, ensuring long-term adoption for DeFi, NFTs, and dApps.
Chapter 2
Ethereum Accounts (EOA vs. Contract Accounts)
Ethereum operates on an account-based model, meaning that every participant interacting with the blockchain—whether an individual user or a decentralized application—does so through an account. Unlike Bitcoin, which uses a UTXO (Unspent Transaction Output) model where transactions reference specific unspent coins, Ethereum maintains a global state that updates account balances and contract data directly.
There are two types of accounts in Ethereum:
- Externally Owned Accounts (EOA) – These accounts are controlled by individuals or entities using private keys. They can initiate transactions, send ETH, and interact with smart contracts.
- Contract Accounts – These accounts are controlled by smart contract code deployed on Ethereum’s blockchain. Unlike EOAs, contract accounts do not have private keys and cannot initiate transactions independently; they only execute code when called by an EOA or another contract.
Understanding these accounts is fundamental to using Ethereum, as they define how transactions are made, how smart contracts function, and how users interact with decentralized applications (dApps). Whether you are making a simple ETH transfer, interacting with a DeFi protocol, or deploying a smart contract, your actions will involve either an EOA, a Contract Account, or both working together.
Externally Owned Accounts (EOA)
What Is an Externally Owned Account?
An Externally Owned Account (EOA) is the most common type of Ethereum account, used by individuals and businesses to send transactions, store ETH, and interact with dApps. It is similar to a bank account in that it holds a balance and allows users to initiate payments, but unlike traditional bank accounts, it operates on a decentralized blockchain with no central authority.
Every EOA consists of:
- A Public Address – A unique identifier that others use to send ETH and tokens to the account.
- A Private Key – A secret key used to sign transactions and prove ownership of the account.
- A Balance of ETH – Required to pay for transaction fees (gas) when interacting with the Ethereum network.
- A Transaction Nonce – A counter that ensures transactions are processed in order and prevents replay attacks.
EOAs are the only accounts that can initiate transactions. Smart contracts (Contract Accounts) cannot perform actions unless they are triggered by an EOA or another contract.
Creating an EOA
To create an Ethereum account, you generate a public-private key pair. This can be done using a wallet like MetaMask, MyEtherWallet, or a hardware wallet such as Ledger or Trezor. Developers can also generate EOAs programmatically using the Ethereum JavaScript library ethers.js.
Example: Generating an EOA with ethers.js
<pre><code class=”language-js”> const { ethers } = require(“ethers”); const wallet = ethers.Wallet.createRandom(); console.log(“Address:”, wallet.address); console.log(“Private Key:”, wallet.privateKey); </code></pre>
Once created, this EOA can receive ETH, send transactions, and interact with smart contracts.
Sending Transactions from an EOA
EOAs send transactions to transfer ETH, interact with smart contracts, or deploy new contracts. Every transaction requires gas fees, which are paid in ETH.
Example: Sending 1 ETH from an EOA to another address
<pre><code class=”language-js”> const provider = new ethers.providers.JsonRpcProvider(“https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID”); const wallet = new ethers.Wallet(“YOUR_PRIVATE_KEY”, provider); const tx = { to: “0xRecipientAddress”, value: ethers.utils.parseEther(“1.0”), }; const sendTx = async () => { const transaction = await wallet.sendTransaction(tx); console.log(“Transaction Hash:”, transaction.hash); }; sendTx(); </code></pre>
Since EOAs are controlled by private keys, it is critical to secure them properly. If someone gains access to your private key, they can control and drain your account.
Contract Accounts
What Is a Contract Account?
A Contract Account is an Ethereum account that is controlled by smart contract code rather than a private key. Unlike EOAs, contract accounts cannot initiate transactions on their own—they can only execute when triggered by an EOA or another contract.
Each contract account has:
- A Unique Ethereum Address – Just like EOAs, contract accounts have an address that users and other contracts can interact with.
- Deployed Smart Contract Code – The contract’s logic is stored on-chain and executes when called.
- State Variables – Contracts can store data persistently on Ethereum’s blockchain.
- ETH Balance – Contract accounts can hold ETH but cannot send it unless programmed to do so.
Contract accounts form the foundation of decentralized applications (dApps) by automating transactions and enforcing business logic without the need for intermediaries.
Deploying a Contract Account (Smart Contract)
Deploying a smart contract creates a new contract account with its own unique address.
Example: A simple Ethereum smart contract that stores a value
<pre><code class=”language-js”> pragma solidity ^0.8.0; contract SimpleStorage { uint public storedValue; function setValue(uint _value) public { storedValue = _value; } } </code></pre>
Once deployed, users interact with the contract by calling its functions from an EOA.
Differences Between EOAs and Contract Accounts
Feature | Externally Owned Account (EOA) | Contract Account |
---|---|---|
Controlled By | Private key | Smart contract code |
Can Initiate Transactions? | Yes | No |
Stores ETH? | Yes | Yes (if programmed to) |
Executes Smart Contracts? | Yes | Only when triggered by an EOA or another contract |
Gas Payment | Paid by the sender | Paid by the calling EOA |
EOAs initiate transactions, while contract accounts execute logic when triggered.
Interaction Models: How EOAs and Contracts Work Together
1. EOA Sending ETH to Another EOA
A direct transaction transfers ETH between two EOAs.
<pre><code class=”language-js”> const tx = { to: “0xRecipientAddress”, value: ethers.utils.parseEther(“1.0”), }; const sendTx = async () => { const transaction = await wallet.sendTransaction(tx); console.log(“Transaction Hash:”, transaction.hash); }; sendTx(); </code></pre>
2. EOA Interacting with a Smart Contract
EOAs can call functions on smart contracts to execute code.
<pre><code class=”language-js”> const contract = new ethers.Contract(contractAddress, contractABI, wallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log(“Transaction confirmed”); }; updateValue(); </code></pre>
3. Smart Contract Calling Another Smart Contract
A contract can call another contract, but only when triggered by an EOA or another contract.
<pre><code class=”language-js”> pragma solidity ^0.8.0; interface IStorage { function storedValue() external view returns (uint); } contract Caller { function getValue(address contractAddress) public view returns (uint) { return IStorage(contractAddress).storedValue(); } } </code></pre>
This allows modular contract design, enabling smart contracts to interact with each other in a decentralized system.
Conclusion
Ethereum’s Externally Owned Accounts (EOA) and Contract Accounts form the foundation of how users interact with the blockchain.
- EOAs are controlled by private keys and initiate transactions.
- Contract Accounts execute predefined code but cannot act independently.
- Smart contracts automate decentralized applications (dApps), enabling DeFi, NFTs, and DAOs.
- Future improvements like account abstraction will blur the lines between EOAs and contract accounts, enhancing security and flexibility.
By understanding Ethereum’s account model, users and developers can build secure applications, manage transactions efficiently, and interact with decentralized finance protocols and blockchain-based services.
Key Concepts
To interact with the Ethereum network, an Externally Owned Account (EOA) creates, signs, and broadcasts a transaction. This process ensures that only the account owner can authorize and execute transactions.
Ethereum transactions contain important details such as:
- Recipient address – Where ETH or contract data is sent.
- Amount of ETH (if applicable) – The amount of ETH being transferred.
- Gas limit – The maximum amount of gas the sender is willing to pay for the transaction to be processed.
- Contract data (optional) – If interacting with a smart contract, this field includes the function call and its parameters.
The transaction must be signed using the private key of the sender’s EOA before being broadcasted to the Ethereum network.
Step 1: Create a Transaction Request
A transaction request is an object that contains the essential transaction details.
Example: Creating a Basic ETH Transfer Transaction
In this example, we create a transaction to send 1 ETH from an EOA to another address.
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const transaction = { to: "0xRecipientAddress", value: ethers.utils.parseEther("1.0"), gasLimit: 21000, maxFeePerGas: ethers.utils.parseUnits("50", "gwei"), maxPriorityFeePerGas: ethers.utils.parseUnits("2", "gwei") }; console.log("Transaction request created:", transaction); </code></pre>
Explanation of the Transaction Fields
- to → The recipient’s Ethereum address.
- value → The amount of ETH to send, converted to wei (smallest ETH unit).
- gasLimit → The gas required to process the transaction (21,000 for simple ETH transfers).
- maxFeePerGas → The maximum gas fee per unit of gas.
- maxPriorityFeePerGas → The miner’s tip, incentivizing faster inclusion in a block.
Step 2: Sign the Transaction Using the Private Key
To authorize and send the transaction, it must be signed using the sender’s private key. Signing ensures that:
- The transaction is legitimate and belongs to the sender.
- No one else can modify it before it is executed on-chain.
Example: Signing a Transaction
<pre><code class="language-js"> const senderPrivateKey = "YOUR_PRIVATE_KEY"; const wallet = new ethers.Wallet(senderPrivateKey, provider); const signTransaction = async () => { const signedTx = await wallet.signTransaction(transaction); console.log("Signed Transaction:", signedTx); }; signTransaction(); </code></pre>
Explanation
- The private key is used to sign the transaction, proving ownership of the sender’s ETH.
- The signed transaction is a cryptographic representation that can be broadcasted to the network.
- Signing does NOT broadcast the transaction—it only prepares it for submission.
Step 3: Broadcast the Transaction to the Ethereum Network
Once signed, the transaction must be broadcasted to the Ethereum network for validation and inclusion in a block.
Example: Sending the Signed Transaction
<pre><code class="language-js"> const sendTransaction = async () => { try { const txResponse = await wallet.sendTransaction(transaction); console.log("Transaction Sent! Hash:", txResponse.hash); await txResponse.wait(); console.log("Transaction Confirmed!"); } catch (error) { console.error("Transaction failed:", error); } }; sendTransaction(); </code></pre>
Explanation
- The transaction is submitted to Ethereum nodes.
- The transaction gets validated and added to a block by network validators.
- The hash (txResponse.hash) is returned, allowing the sender to track the transaction’s status.
- The
wait()
function waits for the transaction to be confirmed and finalized.
You can track the transaction on Etherscan using its transaction hash:
https://etherscan.io/tx/{transaction_hash}
Interacting with Smart Contracts Using EOAs
EOAs can call smart contract functions by including contract data in the transaction request.
Example: Calling a Smart Contract Function
Let’s assume we have a SimpleStorage contract deployed on Ethereum that allows users to store a number.
Solidity Smart Contract (Already Deployed)
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint public storedValue; function setValue(uint _value) public { storedValue = _value; } } </code></pre>
EOA Calling the Smart Contract to Set a Value
<pre><code class="language-js"> const contractAddress = "0xSmartContractAddress"; const contractABI = [ "function setValue(uint _value) public" ]; const contract = new ethers.Contract(contractAddress, contractABI, wallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log("Value updated successfully!"); }; updateValue(); </code></pre>
Here’s what happens:
- The EOA creates a transaction, specifying the contract address and function to call.
- The transaction is signed and broadcasted.
- The Ethereum Virtual Machine (EVM) executes the function, modifying the contract’s state.
- The transaction is confirmed on the blockchain and can be viewed on Etherscan.
Handling Gas Fees
Each transaction requires gas to compensate Ethereum validators for processing transactions.
Estimating Gas Fees
Before submitting a transaction, gas costs can be estimated to avoid failures.
<pre><code class="language-js"> const estimatedGas = await wallet.estimateGas(transaction); console.log("Estimated Gas Cost:", estimatedGas.toString()); </code></pre>
Gas estimates help users set the right gas limits and prevent out-of-gas errors.
Security Considerations
Transactions on Ethereum cannot be reversed, making security a top priority.
1. Protecting Private Keys
- Store keys in hardware wallets (Ledger, Trezor).
- Never expose private keys in code.
- Use multi-signature wallets for added security.
2. Ensuring Smart Contract Safety
- Verify contract addresses before sending transactions.
- Check contract audits and security reports.
- Simulate transactions using tools like Tenderly to preview execution.
Conclusion
To initiate transactions on Ethereum, an EOA must:
- Create a transaction request, specifying the recipient, ETH amount, gas limit, and contract data (if applicable).
- Sign the transaction using its private key, proving ownership and authorization.
- Broadcast the transaction to the Ethereum network, where nodes validate and include it in a block.
EOAs are the gateway to Ethereum, enabling:
- ETH transfers between users.
- Smart contract execution, powering DeFi, NFTs, and DAOs.
- New contract deployments, expanding Ethereum’s decentralized ecosystem.
By following secure transaction practices, users can safely interact with Ethereum while minimizing risks.
Externally Owned Accounts (EOAs) are the only accounts on Ethereum that can initiate transactions. Unlike Contract Accounts, which execute predefined code when triggered, EOAs require a private key to sign transactions and broadcast them to the network. This process ensures that only the owner of the private key can authorize actions like sending ETH, interacting with smart contracts, or deploying new contracts.
Once a transaction is signed and broadcasted, Ethereum nodes validate and execute it, updating the global state of the blockchain.
Steps in the Transaction Lifecycle
- User (EOA owner) initiates a transaction using a wallet or script.
- EOA signs the transaction with its private key to prove authenticity.
- Transaction is broadcasted to the Ethereum network.
- Ethereum nodes validate the transaction and include it in a block.
- The transaction updates the blockchain state, reflecting the new balance or contract execution.
This ensures that only the owner of the private key can trigger transactions, preventing unauthorized actions.
Types of Transactions EOAs Can Initiate
EOAs can initiate three primary types of transactions:
- A simple ETH transfer from one EOA to another.
- A smart contract interaction, calling a function within a deployed contract.
- A contract deployment transaction, creating a new Contract Account on Ethereum.
Each transaction follows the same fundamental process but varies in complexity and execution requirements.
1. Sending ETH from One EOA to Another
The most basic transaction an EOA can initiate is transferring ETH from one account to another. This is similar to sending money between bank accounts but operates without a centralized authority.
Process
- The sender EOA creates a transaction specifying:
- The recipient address.
- The amount of ETH to send.
- A gas limit to pay for network fees.
- The sender signs the transaction using their private key.
- The transaction is broadcasted to the network.
- Ethereum miners/validators verify and confirm the transaction in a block.
- The recipient's balance increases by the transferred amount, and the sender’s balance decreases accordingly.
Example: Sending ETH from One EOA to Another
Using ethers.js, we can initiate a simple ETH transfer.
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const senderWallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const transaction = { to: "0xRecipientAddress", value: ethers.utils.parseEther("1.0"), }; const sendTx = async () => { const tx = await senderWallet.sendTransaction(transaction); await tx.wait(); console.log("Transaction successful! Hash:", tx.hash); }; sendTx(); </code></pre>
Once executed, the recipient will receive 1 ETH, and the sender's balance will be deducted accordingly.
2. Interacting with a Smart Contract
EOAs can also call functions within smart contracts. This is how users interact with DeFi protocols, NFT marketplaces, DAOs, and other dApps on Ethereum.
Since smart contracts do not have private keys, they cannot execute functions on their own. Instead, an EOA must send a transaction to trigger the contract’s execution.
Process
- The EOA creates a transaction specifying:
- The contract’s address.
- The function to call and any required arguments.
- The gas limit and ETH value (if applicable).
- The sender signs the transaction using their private key.
- The transaction is broadcasted to the Ethereum network.
- The Ethereum Virtual Machine (EVM) executes the function within the smart contract.
- The contract updates its internal state or triggers additional logic, such as transferring tokens or storing data.
Example: Calling a Smart Contract Function
Let's assume we have a SimpleStorage contract deployed on Ethereum that allows users to store a number.
Solidity Smart Contract (Already Deployed)
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint public storedValue; function setValue(uint _value) public { storedValue = _value; } } </code></pre>
EOA Calling the Contract to Set a Value
<pre><code class="language-js"> const contractAddress = "0xSmartContractAddress"; const contractABI = [ "function setValue(uint _value) public" ]; const contract = new ethers.Contract(contractAddress, contractABI, senderWallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log("Value updated successfully!"); }; updateValue(); </code></pre>
The EOA initiates the transaction, and the contract updates its stored value on-chain.
This is how users interact with DeFi, NFTs, DAOs, and other blockchain-based applications.
3. Deploying a Smart Contract
EOAs can deploy new smart contracts, creating a Contract Account that lives permanently on Ethereum.
Unlike EOAs, Contract Accounts do not have private keys and execute code automatically when triggered by an EOA or another contract.
Process
- The EOA creates a transaction that contains:
- The smart contract’s compiled bytecode.
- Any constructor arguments (if required).
- A gas limit and ETH value (if necessary).
- The sender signs and broadcasts the transaction.
- The transaction is confirmed on the blockchain, and Ethereum assigns the contract a unique address.
- The smart contract exists permanently on Ethereum and can be interacted with like any other Contract Account.
Example: Deploying a Smart Contract
Using ethers.js, an EOA can deploy the SimpleStorage contract to Ethereum.
<pre><code class="language-js"> const contractBytecode = "0x..."; const contractABI = [ "function setValue(uint _value) public" ]; const contractFactory = new ethers.ContractFactory(contractABI, contractBytecode, senderWallet); const deployContract = async () => { const contract = await contractFactory.deploy(); await contract.deployed(); console.log("Contract deployed at:", contract.address); }; deployContract(); </code></pre>
Once deployed, the contract has its own address, and users can interact with it via transactions.
Why EOAs Are Essential for Ethereum
EOAs serve as the bridge between users and smart contracts, enabling all decentralized applications to function.
Function | EOA Role |
---|---|
Sending ETH | EOAs initiate ETH transfers to other EOAs or smart contracts. |
Calling Smart Contracts | EOAs trigger contract execution (DeFi, NFTs, DAOs). |
Deploying Contracts | EOAs create new Contract Accounts by submitting contract bytecode. |
Without EOAs, Ethereum’s smart contract system would not function because Contract Accounts cannot execute code unless an EOA calls them.
Conclusion
Externally Owned Accounts (EOAs) initiate all transactions on Ethereum, allowing users to:
- Send ETH to other EOAs for payments and transfers.
- Interact with smart contracts to use DeFi, mint NFTs, and vote in DAOs.
- Deploy smart contracts, creating new Contract Accounts on the blockchain.
Since smart contracts cannot act autonomously, EOAs are the only entry point for executing contract logic, making them essential to Ethereum’s decentralized ecosystem.
With future upgrades like account abstraction and Layer 2 scaling, EOAs will become more efficient, secure, and user-friendly, enabling greater accessibility and adoption of Ethereum-based applications.
Ethereum’s Contract Accounts are special accounts on the blockchain that are controlled by smart contract code rather than private keys. Unlike Externally Owned Accounts (EOAs), which are controlled by users and can initiate transactions, Contract Accounts cannot initiate transactions by themselves. Instead, they respond to transactions initiated by EOAs or other smart contracts.
Contract Accounts store and execute smart contracts, which are self-executing programs deployed on the Ethereum blockchain. These contracts define specific rules and logic that automatically execute when triggered by an external transaction. Smart contracts power decentralized applications (dApps), enabling trustless, automated transactions in DeFi, NFTs, DAOs, and more.
Understanding how Contract Accounts store and execute smart contract code is crucial for developers, users, and businesses interacting with Ethereum.
How Contract Accounts Work on Ethereum
Contract Accounts operate differently from EOAs in several key ways:
- They do not have private keys—their execution is determined by on-chain code.
- They cannot send transactions autonomously—they require an EOA or another contract to call them.
- They store code and state on the Ethereum blockchain.
- They execute functions based on predefined logic, responding to transaction inputs.
Contract Accounts provide the foundation for dApps, enabling automated, verifiable execution without centralized control.
How Smart Contract Code Is Stored in Contract Accounts
When a smart contract is deployed to Ethereum, it is converted into bytecode and stored on-chain at a unique contract address.
1. Writing a Smart Contract
Smart contracts on Ethereum are typically written in Solidity, a high-level programming language that compiles down to Ethereum Virtual Machine (EVM) bytecode.
Example: A simple smart contract that stores and updates a value.
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint public storedValue; function setValue(uint _value) public { storedValue = _value; } } </code></pre>
In this contract:
storedValue
is stored persistently on the blockchain.setValue()
updates the stored value when called.- Once deployed, this contract will always execute as programmed, without the need for intermediaries.
2. Deploying a Smart Contract to Ethereum
When a contract is deployed:
- It is compiled into EVM bytecode.
- The bytecode is sent in a transaction from an EOA.
- The blockchain assigns the contract a unique address.
- The contract's code is stored permanently on Ethereum.
Example: Deploying a smart contract using ethers.js
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const contractFactory = new ethers.ContractFactory(contractABI, contractBytecode, wallet); const deployContract = async () => { const contract = await contractFactory.deploy(); await contract.deployed(); console.log("Contract Address:", contract.address); }; deployContract(); </code></pre>
Once deployed, the contract exists on-chain at a permanent Ethereum address.
How Contract Accounts Execute Smart Contract Code
Contract Accounts do not execute automatically—they require an EOA or another contract to call them.
1. Calling a Smart Contract Function
EOAs send transactions to contract accounts to execute functions.
Example: Updating a stored value in the deployed contract
<pre><code class="language-js"> const contract = new ethers.Contract(contractAddress, contractABI, wallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log("Transaction confirmed, value updated!"); }; updateValue(); </code></pre>
- The EOA triggers the transaction by calling
setValue(42)
. - The Ethereum Virtual Machine (EVM) executes the contract logic.
- The contract’s state updates on-chain.
2. Contracts Calling Other Contracts
Contracts can call functions on other contracts when triggered by an EOA.
Example: A contract retrieving data from another contract
<pre><code class="language-js"> pragma solidity ^0.8.0; interface IStorage { function storedValue() external view returns (uint); } contract Caller { function getValue(address contractAddress) public view returns (uint) { return IStorage(contractAddress).storedValue(); } } </code></pre>
This enables modular contract design, where multiple contracts work together to create DeFi platforms, lending protocols, and NFT marketplaces.
Gas Fees: How Contract Accounts Execute Code
Executing smart contract functions requires gas fees, paid in ETH. Since Contract Accounts cannot initiate transactions, the user (EOA) calling the function must pay for gas.
1. Estimating Gas Before Executing a Transaction
Before calling a smart contract function, users can estimate the required gas.
<pre><code class="language-js"> const estimatedGas = await contract.estimateGas.setValue(42); console.log("Estimated Gas Cost:", estimatedGas.toString()); </code></pre>
Gas fees prevent network spam and ensure validators are compensated for processing transactions.
Security Considerations for Contract Accounts
Smart contracts are immutable once deployed, meaning bugs and vulnerabilities cannot be fixed.
1. Common Smart Contract Risks
Risk | Description | Example Exploits |
---|---|---|
Reentrancy Attacks | Malicious contracts repeatedly call functions before the first execution completes. | The DAO Hack (2016) |
Integer Overflow | Large numbers break contract logic. | Early ERC-20 token exploits |
Access Control Issues | Poorly secured contracts allow unauthorized execution. | Hacks on weakly protected admin functions |
2. Preventing Smart Contract Attacks
Developers must follow best practices to secure contract accounts.
Example: Implementing a reentrancy guard
<pre><code class="language-js"> contract SecureContract { bool private locked; modifier noReentrant() { require(!locked, "No reentrancy allowed"); locked = true; _; locked = false; } function withdraw() public noReentrant { // Secure withdrawal logic } } </code></pre>
Using OpenZeppelin security libraries also improves contract safety.
The Future of Contract Accounts
Ethereum is improving contract accounts through Layer 2 scaling and account abstraction.
Upgrade | Impact |
---|---|
Layer 2 Rollups | Reduces gas fees for contract execution |
EIP-1559 | Improves gas fee predictability |
Account Abstraction (EIP-4337) | Allows EOAs to function like smart contract wallets |
Example: Smart contract wallets enabling gasless transactions
<pre><code class="language-js"> contract SmartWallet { address public owner; constructor() { owner = msg.sender; } function executeTransaction(address to, uint amount) public { require(msg.sender == owner, "Not authorized"); payable(to).transfer(amount); } } </code></pre>
With account abstraction, contract accounts will become more user-friendly, making Ethereum more accessible and efficient.
Conclusion
Ethereum’s Contract Accounts store and execute smart contract code, enabling a decentralized ecosystem where applications run without centralized control.
- Contract Accounts do not have private keys—they execute code when called by an EOA.
- Smart contracts store state, execute logic, and interact with other contracts.
- Users must pay gas fees to execute contract functions.
- Security measures, such as reentrancy protection and audits, are essential to preventing attacks.
- Future upgrades like account abstraction will improve how contracts interact with EOAs.
Understanding how Contract Accounts function is essential for developers, businesses, and users engaging with Ethereum’s smart contract ecosystem.
Ethereum’s Externally Owned Accounts (EOAs) and Contract Accounts work together to power decentralized applications (dApps), allowing users to interact with smart contracts, DeFi platforms, NFTs, DAOs, and other blockchain-based services.
EOAs, controlled by private keys, are the only accounts that can initiate transactions. Contract accounts, on the other hand, contain immutable smart contract code that executes when triggered by an external transaction. Together, they enable a trustless, decentralized system where applications run without central authority.
Understanding how EOAs interact with Contract Accounts is crucial for developers, DeFi users, and anyone engaging with Ethereum-based applications.
How EOAs Interact with Contract Accounts
Ethereum’s smart contract ecosystem relies on EOAs to trigger contract execution. Since contract accounts cannot initiate transactions, they depend on EOAs or other contracts to call their functions.
1. Sending ETH to a Contract Account
EOAs can transfer ETH to a smart contract, triggering predefined logic such as staking, swaps, or payments.
Example: Sending 1 ETH to a contract
<pre><code class="language-js"> const tx = { to: "0xSmartContractAddress", value: ethers.utils.parseEther("1.0"), }; const sendTx = async () => { const transaction = await wallet.sendTransaction(tx); await transaction.wait(); console.log("ETH sent successfully!"); }; sendTx(); </code></pre>
When the contract receives ETH, it can store it, execute functions, or redistribute funds based on its logic.
2. EOAs Calling Smart Contract Functions
EOAs interact with smart contracts by calling functions that modify contract state, trigger events, or transfer tokens.
Example: Updating a stored value in a contract
<pre><code class="language-js"> const contract = new ethers.Contract(contractAddress, contractABI, wallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log("Transaction confirmed, value updated!"); }; updateValue(); </code></pre>
The EOA pays gas fees to process the transaction, and the contract updates its state accordingly.
3. Smart Contracts Calling Other Smart Contracts
While contract accounts cannot initiate transactions, they can call other contracts when triggered by an EOA or another contract.
Example: A contract retrieving data from another contract
<pre><code class="language-js"> pragma solidity ^0.8.0; interface IStorage { function storedValue() external view returns (uint); } contract Caller { function getValue(address contractAddress) public view returns (uint) { return IStorage(contractAddress).storedValue(); } } </code></pre>
This enables modular smart contract development, where multiple contracts work together to create complex DeFi platforms, lending protocols, and NFT marketplaces.
Real-World Applications: How EOAs and Contracts Enable dApps
EOAs and contract accounts form the backbone of decentralized applications, providing users with secure, trustless ways to interact with financial services, digital assets, and governance systems.
1. Decentralized Finance (DeFi)
EOAs interact with DeFi protocols to lend, borrow, swap, and earn interest using smart contracts.
Example: Supplying ETH to a lending protocol (Aave)
<pre><code class="language-js"> const aaveLending = new ethers.Contract(aaveAddress, aaveABI, wallet); const depositETH = async () => { const tx = await aaveLending.deposit({ value: ethers.utils.parseEther("1.0") }); await tx.wait(); console.log("1 ETH deposited into Aave!"); }; depositETH(); </code></pre>
The user’s EOA initiates the deposit, and the contract automatically manages lending and interest accrual.
2. Non-Fungible Tokens (NFTs)
EOAs mint, buy, and trade NFTs by interacting with ERC-721 smart contracts.
Example: Minting a new NFT
<pre><code class="language-js"> const nftContract = new ethers.Contract(nftAddress, nftABI, wallet); const mintNFT = async () => { const tx = await nftContract.mintNFT(); await tx.wait(); console.log("NFT minted successfully!"); }; mintNFT(); </code></pre>
The EOA calls the minting function, and the smart contract records ownership on-chain.
3. Decentralized Autonomous Organizations (DAOs)
EOAs interact with DAO governance contracts, voting on proposals and managing decentralized treasuries.
Example: Casting a vote on a DAO proposal
<pre><code class="language-js"> const daoContract = new ethers.Contract(daoAddress, daoABI, wallet); const vote = async (proposalId, support) => { const tx = await daoContract.castVote(proposalId, support); await tx.wait(); console.log("Vote cast successfully!"); }; vote(1, true); </code></pre>
EOAs submit votes, and smart contracts execute governance decisions automatically.
Gas Fees: How Transactions Are Paid
EOAs must pay gas fees when interacting with smart contracts. Contracts cannot pay for transactions, so users need ETH to cover execution costs.
Example: Estimating gas before submitting a transaction
<pre><code class="language-js"> const estimatedGas = await contract.estimateGas.someFunction(); console.log("Estimated Gas Cost:", estimatedGas.toString()); </code></pre>
Gas fees ensure that Ethereum nodes process transactions securely and prevent spam attacks.
Security Considerations: Protecting EOAs and Contracts
Ethereum’s security model ensures that EOAs and contract accounts remain secure, but vulnerabilities can arise if users or developers are careless.
1. Protecting EOAs
- Use hardware wallets for long-term storage.
- Never share private keys or store them online.
- Use multi-signature wallets for added security.
2. Securing Smart Contracts
- Implement reentrancy guards to prevent malicious exploits.
- Use OpenZeppelin libraries for tested, secure contract functions.
- Perform security audits before deploying contracts to mainnet.
Example: Preventing reentrancy attacks
<pre><code class="language-js"> contract SecureContract { bool private locked; modifier noReentrant() { require(!locked, "No reentrancy allowed"); locked = true; _; locked = false; } function withdraw() public noReentrant { // Secure withdrawal logic } } </code></pre>
By securing EOAs and contract accounts, Ethereum ensures reliable, trustless interactions.
The Future of Ethereum Accounts
Ethereum is evolving to improve the interaction between EOAs and smart contracts.
Upgrade | Impact |
---|---|
Account Abstraction (EIP-4337) | Allows EOAs to function like smart contract wallets |
Layer 2 Scaling (Rollups) | Reduces gas fees for contract interactions |
Gas Sponsorship | Enables dApps to pay for user transactions |
Example: Smart contract wallets enabling gasless transactions
<pre><code class="language-js"> contract SmartWallet { address public owner; constructor() { owner = msg.sender; } function executeTransaction(address to, uint amount) public { require(msg.sender == owner, "Not authorized"); payable(to).transfer(amount); } } </code></pre>
With account abstraction, smart wallets will become more user-friendly, improving Ethereum’s accessibility.
Conclusion
Ethereum’s EOAs and contract accounts work together to enable a decentralized ecosystem, allowing users to:
- Send ETH and interact with dApps via EOAs.
- Trigger smart contracts that automate DeFi, NFTs, and DAOs.
- Secure their funds and transactions with best practices.
Future upgrades like account abstraction and Layer 2 scaling will further streamline how users and smart contracts interact, making Ethereum more efficient, accessible, and secure for millions of users worldwide.
Chapter 3
The Ethereum Virtual Machine (EVM)
Ethereum operates as a decentralized computing platform where smart contracts are executed on a global network of nodes. The Ethereum Virtual Machine (EVM) is the computational engine responsible for running these contracts in an isolated, deterministic, and trustless environment.
To interact with the EVM, developers write smart contracts in Solidity, a high-level programming language designed specifically for Ethereum. Solidity code is compiled into EVM bytecode, allowing contracts to be deployed and executed securely on the blockchain.
Understanding the architecture of the EVM, the process of smart contract execution, and the basics of Solidity is essential for developing decentralized applications (dApps) and ensuring secure and efficient contract deployment.
The Ethereum Virtual Machine (EVM) Architecture
The Ethereum Virtual Machine (EVM) is a stack-based virtual machine that operates as an isolated runtime environment for smart contracts. Every Ethereum node runs an instance of the EVM, ensuring consistent execution of smart contracts across all nodes.
Key Features of the EVM
- Deterministic Execution – Given the same inputs, the EVM will always produce the same output.
- Turing-Complete Computation – The EVM can execute any computable logic, but gas constraints prevent infinite loops.
- Isolated Environment – Smart contracts operate in a sandboxed environment, preventing direct access to external systems.
- Stack-Based Architecture – The EVM processes instructions using a Last-In, First-Out (LIFO) stack.
How the EVM Executes Smart Contracts
When a smart contract function is called, the EVM executes a series of low-level operations (opcodes) that manipulate the stack, memory, and storage. These operations consume gas, which must be paid in ETH to incentivize miners/validators to process transactions.
Step-by-Step Smart Contract Execution
- Transaction is sent from an EOA, triggering the contract.
- The transaction is processed by the EVM, which reads the function’s bytecode.
- Opcodes are executed step by step, modifying stack, memory, and storage.
- Gas is consumed for each operation, ensuring computational fairness and preventing spam.
- The final state is recorded on the blockchain, making contract execution immutable.
Each opcode in the EVM has a predefined gas cost, preventing unbounded execution and infinite loops.
Example: Low-Level Execution in the EVM
A simple operation like adding two numbers in Solidity:
<pre><code class=”language-js”> function add(uint256 a, uint256 b) public pure returns (uint256) { return a + b; } </code></pre>
Compiles to EVM opcodes:
<pre><code class=”language-js”> PUSH1 0x02 PUSH1 0x03 ADD </code></pre>
The EVM:
- Pushes values onto the stack.
- Executes the ADD operation.
- Returns the result.
Introduction to Solidity
Solidity is the primary language for writing Ethereum smart contracts. It is statically typed, contract-oriented, and designed for secure execution on the EVM.
Smart contracts written in Solidity are compiled into EVM bytecode, enabling deployment and execution across Ethereum nodes.
Basic Solidity Contract Structure
Every Solidity contract consists of:
- State variables – Data stored permanently on the blockchain.
- Functions – Define contract behavior and modify state.
- Modifiers – Restrict or modify function behavior.
- Events – Emit log data for external listeners.
Example: A basic Solidity contract that stores and retrieves a value.
<pre><code class=”language-js”> pragma solidity ^0.8.0; contract SimpleStorage { uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; } function getValue() public view returns (uint256) { return storedValue; } } </code></pre>
How Solidity Code Compiles into EVM Bytecode
Before a Solidity contract can be deployed, it must be compiled into EVM bytecode. The compilation process involves:
- Converting high-level Solidity code into an Abstract Syntax Tree (AST).
- Generating EVM opcodes from the AST.
- Packaging the bytecode for deployment on Ethereum.
Example: Compiling the SimpleStorage contract into bytecode using Solidity compiler (solc).
<pre><code class=”language-js”> solc –bin SimpleStorage.sol </code></pre>
The output bytecode can then be deployed on Ethereum.
Security and Isolation in the EVM
Since smart contracts handle financial transactions and user data, security is a top priority. The EVM ensures security through:
1. Gas Mechanism to Prevent Infinite Loops
Each EVM operation consumes gas, ensuring contracts cannot execute forever.
2. Contract Isolation
Smart contracts cannot access external files, networks, or system resources, reducing attack vectors.
3. Access Control
Functions can be restricted to specific users or conditions using modifiers.
Example: Restricting access to only the contract owner.
<pre><code class=”language-js”> pragma solidity ^0.8.0; contract SecureContract { address public owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, “Not authorized”); _; } function restrictedFunction() public onlyOwner { // Function logic here } } </code></pre>
Interacting with a Deployed Smart Contract
Once deployed, a contract can be interacted with via transactions.
Example: Calling a contract function using ethers.js.
<pre><code class=”language-js”> const contractAddress = “0xSmartContractAddress”; const contractABI = [ “function setValue(uint256 _value) public”, “function getValue() public view returns (uint256)” ]; const contract = new ethers.Contract(contractAddress, contractABI, wallet); const updateValue = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log(“Smart contract value updated!”); }; updateValue(); </code></pre>
Gas Costs and Optimization in Solidity
Since contract execution requires gas fees, optimizing Solidity code reduces deployment and execution costs.
1. Using Fixed-Size Data Types
Fixed-size variables consume less gas than dynamic arrays or mappings.
<pre><code class=”language-js”> uint256 public counter; // Efficient </code></pre>
2. Minimizing Storage Writes
Writing to blockchain storage is expensive, so updating variables efficiently reduces gas.
<pre><code class=”language-js”> function updateCounter(uint256 _newValue) public { counter = _newValue; } </code></pre>
The Future of the EVM and Solidity
Ethereum continues to improve the EVM with upgrades that enhance performance, security, and developer experience.
Upgrade | Impact |
---|---|
EIP-1559 | Improves gas fee predictability and reduces congestion. |
Optimistic Rollups & ZK-Rollups | Moves contract execution off-chain to reduce fees. |
Account Abstraction (EIP-4337) | Allows EOAs to function more like smart contracts. |
Example: Optimistic Rollups batch multiple transactions, reducing fees.
<pre><code class=”language-js”> batchProcessTransactions(transactions); </code></pre>
These advancements will make Solidity more efficient, improving Ethereum’s scalability and accessibility.
Conclusion
The Ethereum Virtual Machine (EVM) and Solidity work together to enable secure, decentralized computation on the blockchain.
- The EVM executes smart contract bytecode in an isolated environment.
- Opcodes define low-level execution logic, consuming gas to prevent infinite loops.
- Solidity compiles into EVM bytecode, enabling contract deployment and execution.
- Security mechanisms ensure contract safety, preventing malicious code execution.
- Future upgrades will enhance performance and lower transaction costs, improving developer experience.
Understanding how the EVM processes smart contracts and how Solidity compiles into executable code is crucial for building efficient, secure, and scalable decentralized applications.
Key Concepts
https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID is a remote Ethereum node endpoint provided by Infura, which allows applications to interact with the Ethereum blockchain without running a full Ethereum node.
This endpoint connects developers to Ethereum’s Mainnet (live blockchain) via Infura’s high-availability, scalable infrastructure, making it easy to send transactions, query blockchain data, and interact with smart contracts.
Understanding how Infura works, why it is useful, and how to use it in Ethereum applications is essential for building dApps, executing smart contracts, and accessing blockchain data efficiently.
1. Why Use Infura Instead of Running a Full Node?
Ethereum nodes store and validate the entire blockchain, but running a full node requires:
- High Storage Requirements – A full Ethereum node requires hundreds of gigabytes of storage.
- Constant Syncing – The node must stay updated with new blocks.
- Networking and Maintenance – Requires bandwidth and technical upkeep.
Infura provides a remote Ethereum node infrastructure, allowing developers to access the blockchain without maintaining a full node.
Method | Pros | Cons |
---|---|---|
Running a Full Node | Complete control, local data access | Requires high storage, bandwidth, and maintenance |
Using Infura | Easy, scalable, and fast API access | Relies on a third-party provider |
2. What is https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
?
This URL is an RPC (Remote Procedure Call) endpoint, allowing applications to interact with the Ethereum Mainnet through Infura’s API.
Component | Meaning |
---|---|
https://mainnet.infura.io | Infura’s Ethereum Mainnet gateway |
/v3/ | API version 3 |
YOUR_INFURA_PROJECT_ID | A unique identifier for your project |
To use Infura, developers must replace YOUR_INFURA_PROJECT_ID
with a valid project ID, which can be obtained by signing up on Infura.
3. How to Get an Infura Project ID
- Go to Infura’s Website: https://infura.io/
- Sign up for a free account.
- Create a new project.
- Copy the "PROJECT ID" from the project settings.
- Replace
YOUR_INFURA_PROJECT_ID
in the URL with your actual project ID.
Example:https://mainnet.infura.io/v3/abcd1234efgh5678ijkl9012mnop3456
This URL is now your personal API endpoint for accessing Ethereum’s Mainnet.
4. Using Infura in an Ethereum Application
Infura is commonly used with ethers.js and web3.js to interact with Ethereum.
A. Connecting to Infura Using ethers.js
<pre><code class="language-js"> const { ethers } = require("ethers"); // Replace with your Infura Project ID const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const checkBlockNumber = async () => { const blockNumber = await provider.getBlockNumber(); console.log("Current Ethereum Block Number:", blockNumber); }; checkBlockNumber(); </code></pre>
This script:
- Connects to Ethereum via Infura’s Mainnet endpoint.
- Retrieves the latest block number from the blockchain.
B. Sending a Transaction Using Infura
To send a transaction, an EOA must sign the transaction with its private key and broadcast it using Infura.
<pre><code class="language-js"> const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const transaction = { to: "0xRecipientAddress", value: ethers.utils.parseEther("0.1"), gasLimit: 21000 }; const sendTransaction = async () => { const tx = await wallet.sendTransaction(transaction); await tx.wait(); console.log("Transaction successful! Hash:", tx.hash); }; sendTransaction(); </code></pre>
This script:
- Uses Infura to connect to Ethereum.
- Creates and signs a transaction.
- Broadcasts it to the network via Infura.
5. Interacting with Smart Contracts Using Infura
Infura enables applications to read and write data to smart contracts without running a full node.
A. Querying a Smart Contract
Example: Getting the stored value from a SimpleStorage contract.
<pre><code class="language-js"> const contractAddress = "0xSmartContractAddress"; const contractABI = [ "function getValue() public view returns (uint256)" ]; const contract = new ethers.Contract(contractAddress, contractABI, provider); const getValue = async () => { const value = await contract.getValue(); console.log("Stored Value:", value.toString()); }; getValue(); </code></pre>
B. Writing to a Smart Contract
EOAs can also send transactions to update contract state.
Example: Calling setValue()
on a deployed contract.
<pre><code class="language-js"> const contractWithSigner = contract.connect(wallet); const updateValue = async () => { const tx = await contractWithSigner.setValue(42); await tx.wait(); console.log("Contract updated successfully!"); }; updateValue(); </code></pre>
This script:
- Connects to Infura to interact with Ethereum.
- Calls the smart contract’s function to modify blockchain state.
6. Infura’s Role in Ethereum Development
Infura is used for:
- Querying blockchain data without running a full node.
- Sending transactions securely via an API.
- Interacting with smart contracts for dApps.
- Deploying contracts without maintaining an Ethereum client.
Infura supports multiple Ethereum networks:
Network | Endpoint |
---|---|
Ethereum Mainnet | https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID |
Goerli Testnet | https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID |
Sepolia Testnet | https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID |
Developers can test contracts on Goerli or Sepolia before deploying to Mainnet.
7. Alternatives to Infura
While Infura is widely used, there are alternative RPC providers:
Provider | Features |
---|---|
Alchemy | High-speed, scalable Ethereum API |
QuickNode | Low-latency blockchain access |
Ankr | Decentralized RPC provider |
Developers can switch providers by changing the RPC URL in their application.
Example: Using Alchemy instead of Infura
<pre><code class="language-js"> const provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.alchemyapi.io/v2/YOUR_ALCHEMY_API_KEY"); </code></pre>
Conclusion
https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
is a remote Ethereum node endpoint provided by Infura, allowing developers to:
- Access Ethereum’s Mainnet without running a full node.
- Send transactions securely and efficiently.
- Interact with smart contracts from decentralized applications.
By using Infura, developers can focus on building dApps without managing complex Ethereum node infrastructure, making blockchain development faster and more scalable.
The Ethereum Virtual Machine (EVM) is the decentralized runtime environment that executes smart contracts on Ethereum. Every Ethereum node runs an instance of the EVM, ensuring that smart contract execution is consistent, deterministic, and trustless across the network.
To understand how smart contracts are executed, we must break down the EVM's step-by-step process, from receiving a transaction to updating the blockchain state. This includes:
- Transaction Processing: How the EVM receives and validates transactions.
- Bytecode Execution: How Solidity code is compiled and executed using EVM opcodes.
- Stack and Memory Operations: How the EVM processes instructions in a stack-based architecture.
- Gas Consumption: How the EVM prevents infinite execution with gas fees.
- State Changes: How contract storage and blockchain state are updated.
1. Transaction Processing: How the EVM Receives a Transaction
Smart contract execution begins when an Externally Owned Account (EOA) sends a transaction to a Contract Account. The transaction contains:
- The recipient (contract address).
- The gas limit and fees.
- Optional input data (if interacting with a contract function).
Example: Sending a Transaction to a Smart Contract
An EOA sends a transaction to a SimpleStorage contract to update its stored value.
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const contractAddress = "0xSmartContractAddress"; const contractABI = [ "function setValue(uint256 _value) public" ]; const contract = new ethers.Contract(contractAddress, contractABI, wallet); const sendTransaction = async () => { const tx = await contract.setValue(42); await tx.wait(); console.log("Transaction confirmed!"); }; sendTransaction(); </code></pre>
2. Bytecode Execution: Converting Solidity Code into EVM Opcodes
Before execution, Solidity code is compiled into EVM bytecode, a series of low-level instructions (opcodes) that the EVM understands.
Example: Solidity Code
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; } } </code></pre>
Compiled EVM Bytecode
This Solidity function compiles into EVM opcodes like:
<pre><code class="language-js"> PUSH1 0x02 PUSH1 0x03 ADD SSTORE </code></pre>
The EVM executes these instructions step by step using its stack-based execution model.
3. Stack and Memory Operations in the EVM
The EVM is a stack-based machine, meaning it processes data using a Last-In, First-Out (LIFO) stack.
How the Stack Works
- Instructions push data onto the stack.
- Opcodes process data on the stack.
- Results are stored back into the stack or contract storage.
Example: Adding Two Numbers in the EVM
Solidity Code:
<pre><code class="language-js"> function add(uint256 a, uint256 b) public pure returns (uint256) { return a + b; } </code></pre>
Compiled EVM Execution:
<pre><code class="language-js"> //PUSH1 0x02 Push 2 onto the stack PUSH1 0x03 // Push 3 onto the stack ADD // Add top two values (2 + 3 = 5) </code></pre>
After execution, the result (5) is left on the stack and can be returned to the caller.
4. Gas Consumption: Preventing Infinite Execution
Each EVM operation consumes gas, preventing infinite loops and excessive computation.
Gas Cost Per Operation
Opcode | Gas Cost |
---|---|
ADD | 3 gas |
SSTORE (storing data in contract storage) | 20,000 gas |
CALL (calling another contract) | 700 gas |
LOG (emitting an event) | 375 gas |
If a transaction exceeds its gas limit, the EVM halts execution and reverts the transaction, but the sender still pays for used gas.
Example: Estimating Gas Before Sending a Transaction
<pre><code class="language-js"> const estimatedGas = await contract.estimateGas.setValue(42); console.log("Estimated Gas Cost:", estimatedGas.toString()); </code></pre>
This ensures the sender has enough ETH to pay for the transaction.
5. State Changes: Updating Storage and Blockchain State
Once execution completes, the EVM updates the contract’s storage and reflects the changes in the blockchain state.
Contract Storage Example
<pre><code class="language-js"> SSTORE 0x01 0x42 </code></pre>
This instruction:
- Stores the value
42
at storage slot0x01
in the smart contract. - Persists the value across transactions.
Example: Retrieving Stored Data in Solidity
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; } function getValue() public view returns (uint256) { return storedValue; } } </code></pre>
Calling getValue()
reads from contract storage and returns the stored value.
6. Finalizing Execution: Returning Results and Emitting Events
Once a contract function executes, the EVM:
- Returns the result to the caller (if applicable).
- Emits events for logging and external monitoring.
Example: Emitting an Event After Execution
<pre><code class="language-js"> pragma solidity ^0.8.0; contract EventExample { event ValueUpdated(uint256 newValue); uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; emit ValueUpdated(_value); } } </code></pre>
After execution, the event is stored in Ethereum logs, allowing external applications to track contract activity.
Summary of EVM Execution Steps
Step | Process |
---|---|
1. Transaction Processing | An EOA sends a transaction to a smart contract. |
2. Bytecode Execution | Solidity code is compiled into EVM bytecode and executed. |
3. Stack and Memory Operations | Data is processed using the stack and memory. |
4. Gas Consumption | Each operation deducts gas, preventing infinite execution. |
5. State Changes | Storage updates modify the blockchain state. |
6. Finalizing Execution | The EVM returns results and emits logs for external tracking. |
The entire execution must complete within the gas limit; otherwise, it reverts to the previous state.
Conclusion
The EVM ensures secure, deterministic execution of smart contracts by:
- Processing transactions from EOAs.
- Executing Solidity code as EVM bytecode.
- Using a stack-based model for computation.
- Charging gas fees to prevent infinite execution.
- Updating contract storage upon successful execution.
- Logging execution results through emitted events.
Understanding this step-by-step execution process is critical for developing secure and efficient smart contracts, ensuring decentralized applications run smoothly on Ethereum.
Solidity is a high-level programming language specifically designed for developing smart contracts on Ethereum. It allows developers to define immutable, decentralized applications that run on the Ethereum Virtual Machine (EVM).
Solidity code must be compiled into EVM bytecode before deployment. The compiler translates human-readable Solidity code into low-level machine instructions (opcodes) that the EVM can execute. Understanding Solidity’s core features and how it translates into bytecode is essential for secure and efficient smart contract development.
Core Features of Solidity
Solidity provides several built-in features to facilitate smart contract programming, ensuring secure and efficient execution on Ethereum.
1. Contract Structure and State Variables
Solidity contracts define state variables that store persistent data on the blockchain. State variables hold values that remain unchanged between transactions unless explicitly modified.
Example: Basic Contract with State Variables
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SimpleStorage { uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; } function getValue() public view returns (uint256) { return storedValue; } } </code></pre>
Here:
storedValue
is a state variable that stores data persistently on the blockchain.setValue()
updates the stored value.getValue()
reads the stored value without modifying the blockchain.
2. Data Types and Variable Scope
Solidity supports various data types, including integers, addresses, booleans, and more.
Example: Different Data Types in Solidity
<pre><code class="language-js"> pragma solidity ^0.8.0; contract DataTypes { uint256 public number = 100; bool public isActive = true; address public owner; constructor() { owner = msg.sender; } } </code></pre>
Solidity enforces strict variable scoping, ensuring that:
- State variables persist across transactions.
- Local variables exist only within the function that declares them.
3. Functions and Visibility Modifiers
Functions in Solidity can have different visibility modifiers, controlling who can call them.
Modifier | Description |
---|---|
public | Anyone can call the function. |
private | Only the contract itself can call the function. |
internal | Only the contract and derived contracts can access the function. |
external | Can only be called from outside the contract. |
Example: Using Function Modifiers
<pre><code class="language-js"> pragma solidity ^0.8.0; contract VisibilityExample { uint256 private secretNumber; function setSecret(uint256 _number) public { secretNumber = _number; } function getSecret() internal view returns (uint256) { return secretNumber; } } </code></pre>
4. Control Structures (Loops and Conditionals)
Solidity supports control flow statements like loops and conditionals to execute logic based on conditions.
Example: Using Conditionals and Loops
<pre><code class="language-js"> pragma solidity ^0.8.0; contract ControlStructures { function checkNumber(uint256 _num) public pure returns (string memory) { if (_num > 10) { return "Greater than 10"; } else { return "10 or less"; } } function sumNumbers(uint256 _limit) public pure returns (uint256) { uint256 sum = 0; for (uint256 i = 0; i <= _limit; i++) { sum += i; } return sum; } } </code></pre>
5. Events and Logging
Events allow smart contracts to emit log messages, which external applications can listen to.
Example: Emitting an Event in Solidity
<pre><code class="language-js"> pragma solidity ^0.8.0; contract EventExample { event ValueUpdated(uint256 newValue); uint256 public storedValue; function setValue(uint256 _value) public { storedValue = _value; emit ValueUpdated(_value); } } </code></pre>
Here, when setValue()
is called, the contract logs the new value as an event.
6. Security Mechanisms in Solidity
Solidity provides built-in security mechanisms to protect contracts from common vulnerabilities.
Access Control Using Modifiers
Example: Restricting Function Access to the Contract Owner
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SecureAccess { address public owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _; } function restrictedFunction() public onlyOwner { // Restricted logic here } } </code></pre>
How Solidity Compiles to EVM Bytecode
Before a Solidity contract can be deployed and executed, it must be compiled into EVM bytecode.
Compilation Process
- Parsing – The Solidity compiler (
solc
) converts the code into an Abstract Syntax Tree (AST). - Bytecode Generation – The compiler converts AST into EVM opcodes.
- Deployment Bytecode – The final compiled contract contains constructor data and runtime logic.
Example: Compiling a Solidity Contract Using solc
<pre><code class="language-js"> solc --bin SimpleStorage.sol </code></pre>
This command outputs the contract’s bytecode, which can be deployed on Ethereum.
EVM Bytecode and Opcodes
The EVM executes bytecode, which consists of low-level machine instructions (opcodes).
Example: Solidity Code and Its Corresponding Opcodes
Solidity function:
<pre><code class="language-js"> function add(uint256 a, uint256 b) public pure returns (uint256) { return a + b; } </code></pre>
Compiles to EVM opcodes:
<pre><code class="language-js"> PUSH1 0x02 PUSH1 0x03 ADD </code></pre>
The EVM processes these instructions sequentially, using a stack-based execution model.
Interacting with Compiled Smart Contracts
Once compiled, smart contracts can be deployed and interacted with.
Example: Deploying a Smart Contract with ethers.js
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const contractFactory = new ethers.ContractFactory(contractABI, contractBytecode, wallet); const deployContract = async () => { const contract = await contractFactory.deploy(); await contract.deployed(); console.log("Contract deployed at:", contract.address); }; deployContract(); </code></pre>
This process creates a new Contract Account, allowing users to interact with its functions.
Conclusion
Solidity provides structured, secure programming for Ethereum smart contracts, offering:
- Core features like state variables, functions, loops, and events.
- Security mechanisms such as access control and reentrancy protection.
- A compilation process that converts Solidity into EVM-executable bytecode.
- Opcodes that the EVM executes in a stack-based computing environment.
Understanding Solidity’s features and compilation process is essential for developing, deploying, and optimizing smart contracts in Ethereum’s decentralized ecosystem.
The Ethereum Virtual Machine (EVM) is designed to execute smart contracts in a secure, deterministic, and decentralized environment. Because smart contracts are immutable and often handle financial transactions, user data, and decentralized governance, they must be protected from malicious behavior and vulnerabilities.
To ensure security, the EVM enforces strict execution rules, gas limits, and isolation mechanisms, preventing exploits such as infinite loops, unauthorized access, and reentrancy attacks.
Understanding how the EVM safeguards smart contracts is essential for developers, auditors, and users interacting with decentralized applications (dApps) on Ethereum.
1. The EVM’s Isolation Mechanism: Sandbox Execution
The EVM runs each smart contract in a sandboxed (isolated) environment, meaning that:
- Contracts cannot directly access external systems, files, or networks.
- A contract cannot modify another contract’s state unless explicitly called.
- Execution is deterministic, meaning that given the same inputs, a contract will always produce the same outputs.
This isolation ensures that malicious contracts cannot compromise the Ethereum network or affect other smart contracts.
Example: A contract cannot directly read from or write to an external API:
<pre><code class="language-js"> pragma solidity ^0.8.0; contract IsolatedContract { function externalCall() public pure returns (string memory) { return "This contract cannot fetch data from external servers!"; } } </code></pre>
2. Gas Mechanism: Preventing Infinite Loops and Spam Attacks
Each operation executed in the EVM consumes gas, which must be paid by the sender of the transaction. This mechanism:
- Prevents infinite loops that could crash or congest the network.
- Stops denial-of-service (DoS) attacks, where malicious actors attempt to overload the blockchain.
- Ensures fair computation costs, making spam attacks costly and impractical.
How Gas Limits Work
- Before execution, the sender specifies a gas limit.
- If execution exceeds the gas limit, the transaction fails and reverts.
- If execution completes with leftover gas, the sender receives a refund.
Example: A contract function that loops indefinitely but will be halted by gas limits:
<pre><code class="language-js"> pragma solidity ^0.8.0; contract InfiniteLoop { function loopForever() public pure { while (true) { } } } </code></pre>
This function will never execute successfully, as it would exceed the gas limit and revert.
3. Reentrancy Protection: Preventing Recursive Attacks
One of the most infamous Ethereum vulnerabilities is reentrancy, where a malicious contract repeatedly calls a function before the previous execution is complete, draining funds from the contract.
How the EVM Prevents Reentrancy
- State changes occur before external calls to prevent repeated withdrawals.
- Developers use the "Checks-Effects-Interactions" pattern, ensuring funds are updated before external transfers.
- Reentrancy guards (mutexes) prevent multiple calls to the same function within a single execution.
Example: Vulnerable Smart Contract Without Reentrancy Protection
<pre><code class="language-js"> pragma solidity ^0.8.0; contract VulnerableContract { mapping(address => uint) public balances; function withdraw() public { require(balances[msg.sender] > 0, "No funds available"); (bool success, ) = msg.sender.call{value: balances[msg.sender]}(""); require(success, "Transfer failed"); balances[msg.sender] = 0; } } </code></pre>
An attacker could create a malicious contract that repeatedly calls withdraw()
before balances[msg.sender] = 0
executes, draining funds.
Safe Version Using Reentrancy Guard
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SecureContract { mapping(address => uint) public balances; bool private locked; modifier noReentrant() { require(!locked, "Reentrancy detected"); locked = true; _; locked = false; } function withdraw() public noReentrant { require(balances[msg.sender] > 0, "No funds available"); uint amount = balances[msg.sender]; balances[msg.sender] = 0; (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Transfer failed"); } } </code></pre>
Here, the noReentrant
modifier prevents recursive calls, securing the contract.
4. Access Control: Restricting Unauthorized Transactions
Smart contracts must prevent unauthorized users from executing sensitive functions. The EVM allows developers to restrict functions using:
- Modifiers that limit access to the contract owner.
- Role-based permissions to grant different users different levels of access.
Example: Restricting Function Access to the Contract Owner
<pre><code class="language-js"> pragma solidity ^0.8.0; contract SecureAccess { address public owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _; } function restrictedFunction() public onlyOwner { } } </code></pre>
This ensures that only the contract owner can call restrictedFunction()
, protecting sensitive operations.
5. Immutable Code and Smart Contract Upgrades
Once a contract is deployed, its code cannot be modified. This immutability protects contracts from post-deployment tampering but also means bugs cannot be fixed directly.
Solutions for Smart Contract Upgrades
- Proxy Contracts – Instead of modifying a contract, developers deploy a new version and use a proxy contract to redirect calls to the updated logic.
- Self-Destruct Mechanism – Some contracts include a
selfdestruct()
function to remove the contract and allow redeployment. - Modular Smart Contracts – Contracts are designed as separate upgradeable modules, allowing different parts to be updated without affecting the entire contract.
Example: Proxy Contract Pattern for Upgrading Contracts
<pre><code class="language-js"> pragma solidity ^0.8.0; contract Proxy { address public implementation; function upgradeTo(address newImplementation) public { implementation = newImplementation; } fallback() external payable { address impl = implementation; require(impl != address(0), "Implementation not set"); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0) returndatacopy(ptr, 0, returndatasize()) switch result case 0 { revert(ptr, returndatasize()) } default { return(ptr, returndatasize()) } } } } </code></pre>
This contract forwards function calls to an upgradeable implementation contract, allowing changes without redeploying the entire system.
6. Preventing Integer Overflows and Underflows
Older versions of Solidity allowed integer overflows, where a value exceeding the max limit would wrap around to zero. The latest Solidity versions automatically check for overflows, but developers should still be cautious.
Example of Overflow Vulnerability in Older Solidity Versions
<pre><code class="language-js"> pragma solidity ^0.4.24; contract OverflowVulnerable { uint8 public counter = 255; function increment() public { counter += 1; } } </code></pre>
Calling increment()
would reset counter to zero, due to overflow.
Safe Version Using Solidity 0.8+ with Built-in Overflow Checks
<pre><code class="language-js"> pragma solidity ^0.8.0; contract OverflowProtected { uint8 public counter = 255; function increment() public { counter += 1; } } </code></pre>
Newer Solidity versions automatically prevent overflows, reverting the transaction if an overflow occurs.
Conclusion
The EVM ensures security by implementing:
- Sandbox execution, preventing contracts from accessing external systems.
- Gas limits, stopping infinite loops and DoS attacks.
- Reentrancy guards, securing contracts against recursive exploits.
- Access control mechanisms, restricting unauthorized function execution.
- Upgrade patterns, enabling contract improvements while maintaining immutability.
- Overflow protection, preventing integer vulnerabilities.
By understanding these security mechanisms, developers can write safer smart contracts, minimizing risks and enhancing Ethereum’s trustless and decentralized environment.
Chapter 4
Block Structure & Uncle Blocks
Ethereum’s block structure contains essential components that maintain network integrity, track transactions, and enforce consensus. Unlike Bitcoin, Ethereum introduces uncle blocks (ommer blocks)—valid blocks that were mined almost simultaneously with the canonical chain but were not included in it.
These uncle blocks play a key role in:
- Improving network security by reducing orphan blocks.
- Providing incentives to miners who contribute computational power but miss inclusion in the main chain.
- Reducing the advantage of large mining pools, decentralizing mining rewards.
Understanding Ethereum’s block structure and uncle block mechanism is critical to grasping how Ethereum ensures fair mining, reduces chain splits, and maintains security.
1. Structure of an Ethereum Block
Each Ethereum block contains:
- A Header – Metadata that helps track block properties.
- A List of Transactions – The actual smart contract interactions and ETH transfers.
- State Root & Receipts Root – Cryptographic hashes that summarize blockchain state changes.
Ethereum Block Structure
Component | Description |
---|---|
Block Header | Contains metadata such as the parent block hash, timestamp, and difficulty. |
Transactions | A list of all transactions included in the block. |
State Root | The Merkle root hash representing the global state after executing transactions. |
Receipts Root | A hash summarizing transaction receipts (logs, gas usage, execution results). |
Uncles (Ommers) | A list of referenced uncle blocks. |
2. What Are Uncle Blocks (Ommer Blocks)?
Uncle blocks (formerly called ommer blocks) are valid but stale blocks that were mined around the same time as another block but were not added to the main chain.
Since Ethereum uses short block times (~12-15 seconds), it is possible for multiple miners to solve a block almost simultaneously. However, only one block can be added to the canonical chain, while others become uncle blocks.
Why Do Uncle Blocks Exist?
- Ethereum’s fast block time increases the chance of near-simultaneous blocks.
- Network latency may cause different nodes to temporarily disagree on the latest block.
- Without uncle block rewards, smaller miners would be at a disadvantage, leading to centralization.
Uncle blocks help secure the network by rewarding miners who contribute valid blocks, even if their block was not added to the main chain.
3. How Uncle Blocks Are Included in Ethereum
Ethereum allows miners to reference up to two uncle blocks per new block, helping miners who lost out on the main chain still earn partial rewards.
Rules for a Valid Uncle Block
To be considered valid, an uncle block must:
- Be a valid block mined according to Ethereum’s consensus rules.
- Not be the canonical block in the chain.
- Be referenced within the next six blocks after it was mined.
- Share the same parent as the canonical block but not extend beyond six generations.
If a miner includes an uncle block reference, they receive extra rewards, and the miner of the uncle block also receives a partial mining reward.
4. Incentive Model: How Uncle Blocks Reduce Centralization Risk
Ethereum’s uncle block reward system prevents large mining pools from dominating the network.
Mining Reward Breakdown
- The canonical block miner receives the full block reward.
- The uncle block miner receives 7/8 of the full block reward.
- The miner who includes an uncle block reference receives 1/32 of the block reward per uncle block.
This incentivizes miners to continue mining even if their blocks do not make it to the main chain, reducing the centralization advantage of large pools.
Example: Uncle Block Reward Calculation
If the base block reward is 2 ETH, then:
- The uncle block miner receives 7/8 × 2 ETH = 1.75 ETH.
- The miner who references the uncle receives 1/32 × 2 ETH = 0.0625 ETH per uncle block.
This makes uncle blocks an important part of Ethereum’s incentive mechanism, promoting decentralization and network security.
5. Difference Between Ethereum and Bitcoin Block Handling
Unlike Ethereum, Bitcoin does not reward orphaned blocks. When two miners solve a Bitcoin block at the same time, only one block is included, and the other is discarded without compensation.
Feature | Ethereum (Uncle Blocks) | Bitcoin (Orphan Blocks) |
---|---|---|
Reward for Stale Blocks? | Yes, miners of uncle blocks receive rewards. | No, orphaned blocks receive nothing. |
Block Time | ~12-15 seconds | ~10 minutes |
Purpose | Reduces mining centralization, rewards miners for valid work. | No incentives for orphan blocks, leading to higher centralization. |
Bitcoin miners must wait 10 minutes per block, making stale blocks less common, while Ethereum’s fast block times make uncle blocks an essential part of network security.
6. How Uncle Blocks Are Tracked in Ethereum
Uncle blocks are stored in the block header and can be retrieved using Ethereum JSON-RPC.
Checking Uncle Blocks Using ethers.js
<pre><code class=”language-js”> const { ethers } = require(“ethers”); const provider = new ethers.providers.JsonRpcProvider(“mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID”); const getBlockWithUncles = async (blockNumber) => { const block = await provider.getBlock(blockNumber); console.log(“Block Number:”, block.number); console.log(“Uncle Blocks:”, block.uncles); }; getBlockWithUncles(15000000); </code></pre>
This script retrieves the number of uncle blocks in a specific Ethereum block.
7. Uncle Blocks and Ethereum 2.0 (The Merge)
With Ethereum’s transition to Proof of Stake (PoS) under The Merge, uncle blocks have been replaced with a different concept called “missed slots”.
Feature | Ethereum PoW (Before The Merge) | Ethereum PoS (After The Merge) |
---|---|---|
Uncle Blocks | Miners were rewarded for valid, stale blocks. | No uncle blocks in PoS. |
Missed Slots | Not applicable in PoW. | Validators who fail to propose a block miss their reward. |
Block Time | ~12-15 seconds. | ~12 seconds (deterministic). |
In PoS, the need for uncle block rewards is eliminated, as validators propose blocks deterministically rather than competing for mining rewards.
Conclusion
Ethereum’s block structure and uncle block mechanism play a crucial role in ensuring:
- Fair mining incentives, preventing wasted computational power.
- Decentralization, by reducing the advantage of large mining pools.
- Network security, by including near-miss blocks instead of discarding them.
With Ethereum’s shift to Proof of Stake (PoS), uncle blocks are no longer needed, but their historical impact on Ethereum’s fair and decentralized mining system remains a key part of Ethereum’s evolution.
Key Concepts
Ethereum’s blockchain consists of a series of blocks, each containing critical information that ensures the network remains secure, immutable, and synchronized. These blocks store transaction data, cryptographic proofs, and state updates that enable the Ethereum Virtual Machine (EVM) to execute smart contracts and maintain decentralized consensus.
Each Ethereum block consists of three major components:
- Block Header – Contains metadata such as timestamps, difficulty, and references to previous blocks.
- Transactions List – Stores executed transactions and contract interactions.
- State Information – Includes cryptographic roots that track Ethereum’s account balances, storage, and logs.
These components work together to ensure network integrity, prevent tampering, and enable Ethereum’s decentralized execution model.
1. The Block Header: Metadata That Links Ethereum’s Blockchain
The block header is the most crucial part of an Ethereum block. It acts as the identifier for the block and contains cryptographic hashes, timestamps, and consensus-related data.
Key Fields in the Ethereum Block Header
Field | Description |
---|---|
Parent Hash | The hash of the previous block, linking blocks together in a chain. |
Uncle Hash | A reference to valid, but not included, uncle blocks. |
State Root | The Merkle root hash representing the entire Ethereum state. |
Transactions Root | A Merkle root of all transactions included in this block. |
Receipts Root | A Merkle root summarizing all transaction receipts. |
Block Number | The sequential identifier for the block. |
Timestamp | The Unix timestamp when the block was created. |
Nonce (Pre-Merge) | The proof-of-work value that allowed miners to mine the block. |
Difficulty (Pre-Merge) | The measure of how hard it was to mine this block. |
Base Fee Per Gas | The minimum gas fee required for transactions (introduced in EIP-1559). |
How the Block Header Maintains Blockchain Integrity
- The Parent Hash ensures that each block references the previous block, preventing data tampering.
- The State Root, Transactions Root, and Receipts Root provide cryptographic proofs that ensure transaction data remains valid and unchanged.
- The Timestamp and Block Number keep the blockchain in chronological order, preventing reordering attacks.
2. Transactions List: The Core Data of an Ethereum Block
Each Ethereum block contains a list of transactions, including ETH transfers, smart contract executions, and token interactions.
Structure of a Transaction in Ethereum
Each transaction includes:
Field | Description |
---|---|
Nonce | A counter that ensures transactions execute in order. |
Gas Price | The fee the sender is willing to pay for execution. |
Gas Limit | The maximum gas the sender is willing to spend. |
Recipient Address | The EOA or contract the transaction is directed to. |
Value | The amount of ETH being transferred. |
Data | Contains smart contract function calls and parameters. |
V, R, S | Cryptographic values proving the transaction was signed by the sender. |
Example: Ethereum Transaction JSON Structure
<pre><code class="language-js"> { "nonce": 10, "gasPrice": "20000000000", "gasLimit": "21000", "to": "0xRecipientAddress", "value": "1000000000000000000", "data": "", "v": "0x1c", "r": "0xa1b2c3...", "s": "0x4d5e6f..." } </code></pre>
How Transactions Maintain Blockchain Integrity
- Digital Signatures (V, R, S fields) ensure only the account owner can authorize transactions.
- The Nonce prevents replay attacks, ensuring transactions execute in the correct order.
- Gas limits and fees prevent infinite execution, maintaining network stability.
3. State Information: Tracking Ethereum’s Global State
Ethereum is a stateful blockchain, meaning that every block contains an updated version of the global state, which includes account balances, smart contract storage, and logs.
The block header contains three Merkle roots that provide cryptographic proofs of the state:
State Root
- A Merkle Patricia Trie root hash that represents Ethereum’s entire global state at a given block.
- Stores account balances, smart contract storage, and execution results.
Transactions Root
- A Merkle root hash summarizing all transactions in the block.
Receipts Root
- A Merkle root hash summarizing all transaction receipts (logs, events, and execution outcomes).
How Ethereum’s State Maintains Blockchain Integrity
- State consistency is enforced by Merkle Trees, allowing efficient verification.
- Storage modifications are recorded in the block header, ensuring transactions correctly update the blockchain.
- Nodes can verify transactions without downloading the entire blockchain, improving scalability.
4. How Ethereum Blocks Are Validated and Finalized
Ethereum achieves consensus and finality through the block validation process:
Step 1: A Node Receives a New Block Proposal
- The block’s parent hash is checked to ensure it builds on the correct chain.
- The block’s timestamp is verified to prevent artificial delays.
Step 2: Transactions Are Executed and Validated
- Each transaction is re-executed in the EVM, ensuring correct state updates.
- Digital signatures are checked to prevent forgery or unauthorized transactions.
Step 3: The Block’s Merkle Roots Are Verified
- The State Root, Transactions Root, and Receipts Root are recomputed to confirm data integrity.
Step 4: The Block Is Added to the Chain
- If the block is valid, it is broadcasted to the network and included in the blockchain.
5. How Ethereum’s Block Structure Prevents Attacks
Ethereum’s block structure protects against several security risks, including:
Attack Type | Ethereum’s Protection Mechanism |
---|---|
Double Spending | Blocks reference previous state roots, preventing modification of past transactions. |
Sybil Attacks | Validators in PoS must stake ETH, making attacks costly. |
Replay Attacks | Nonce values enforce transaction order and prevent replays. |
Infinite Execution | Gas limits prevent malicious contracts from running indefinitely. |
6. How to Retrieve Ethereum Block Data Using ethers.js
Developers can use ethers.js to inspect Ethereum blocks.
Fetching the Latest Ethereum Block
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const getLatestBlock = async () => { const block = await provider.getBlock("latest"); console.log("Block Number:", block.number); console.log("Block Hash:", block.hash); console.log("Transactions Root:", block.transactionsRoot); console.log("State Root:", block.stateRoot); }; getLatestBlock(); </code></pre>
This script retrieves:
- The latest block number.
- The block hash (unique identifier).
- The transactions and state root.
Conclusion
Ethereum’s block structure maintains blockchain integrity by:
- Using cryptographic hashes to link blocks together, preventing tampering.
- Tracking transactions and smart contract execution, ensuring state consistency.
- Using Merkle trees to verify storage updates, making the blockchain efficient and secure.
- Following strict validation steps, ensuring only valid blocks are added.
Understanding Ethereum’s block structure and validation process is essential for building secure and scalable decentralized applications (dApps).
Ethereum’s uncle blocks (ommer blocks) are an essential component of its Proof of Work (PoW) consensus mechanism, designed to:
- Reduce the impact of network latency by rewarding blocks that were valid but not included in the main chain.
- Improve decentralization by making mining rewards more accessible to smaller miners.
- Enhance network security by ensuring that miners continue participating even if their blocks do not get added to the canonical chain.
Uncle blocks arise when multiple miners solve a block at nearly the same time, but only one block is accepted into the main chain. Instead of discarding the unused blocks, Ethereum allows them to be referenced and partially rewarded, ensuring their computational work is not wasted.
1. What Are Uncle Blocks (Ommer Blocks)?
An uncle block is a valid block that was mined but not included in the main Ethereum blockchain due to another miner successfully broadcasting their block first.
Ethereum uses short block times (~12-15 seconds), which increases the likelihood of multiple miners solving a block at the same time. Since the network can only accept one block per slot, others become uncle blocks rather than being completely orphaned.
In Ethereum:
- Canonical blocks form the main chain.
- Uncle blocks are those that were valid but did not make it into the main chain.
2. Why Do Uncle Blocks Occur?
Uncle blocks occur due to the distributed nature of Ethereum’s mining network, where nodes:
- Do not instantly receive updates about newly mined blocks.
- Continue mining on outdated chain data for a short period.
- Solve a block that is valid but was beaten by another miner’s block.
The main reasons for uncle block formation include:
- Network Latency – Some nodes receive new blocks slightly later than others, leading to temporary chain forks.
- Propagation Delays – Large networks take time to sync, so some miners unknowingly build on outdated data.
- Fast Block Times – Ethereum’s ~12-second block interval increases the chance of simultaneous block solutions.
3. How Ethereum Includes Uncle Blocks in the Blockchain
Ethereum allows miners to reference uncle blocks within their new blocks, providing a way to reward the miners of uncle blocks while maintaining consensus.
- Up to two uncle blocks can be included in a new Ethereum block.
- Uncle blocks must be no older than six blocks behind the current block.
- Both the miner of the uncle block and the referencing miner receive rewards.
If a miner successfully mines an uncle block but does not make it into the main chain, another miner can include it as an uncle block reference, ensuring the miner still earns a partial reward.
4. How Uncle Blocks Are Rewarded
Ethereum uses an incentive model to compensate both:
- The miner who originally mined the uncle block.
- The miner who includes the uncle block reference in their new block.
Uncle Block Miner’s Reward
If the full block reward is R
(e.g., 2 ETH per block), then an uncle block miner receives:
(7/8) × R
(87.5% of the full block reward).
Example:
If R = 2 ETH, then:
- The uncle block miner receives 1.75 ETH.
Main Block Miner’s Reward for Including an Uncle Block
The miner who references an uncle block receives:
(1/32) × R
per uncle block included.
Example:
- If R = 2 ETH, then the referencing miner gets 0.0625 ETH per uncle block.
- A single block can include up to two uncle blocks, allowing an additional 0.125 ETH per block.
These rewards incentivize honest mining participation, even if a miner's block does not immediately become part of the canonical chain.
5. Importance of Uncle Blocks in Ethereum’s Consensus Mechanism
Ethereum’s uncle block mechanism plays a vital role in consensus, security, and decentralization.
1. Reducing Network Centralization
Without uncle block rewards:
- Larger mining pools would have an unfair advantage because they can propagate blocks faster.
- Small and solo miners would be disproportionately disadvantaged due to slower block propagation times.
- The network would become more centralized as miners consolidate into fewer, larger pools.
By rewarding uncle blocks, Ethereum ensures that miners continue participating even if their blocks do not make it into the main chain.
2. Improving Network Security
Uncle blocks improve Ethereum’s security by:
- Increasing overall hash power, since miners remain active even if their blocks are not added to the main chain.
- Reducing incentives to attack the network, since miners are compensated fairly.
- Preventing wasted computational work, making the network more efficient.
3. Enhancing Blockchain Liveness
Ethereum’s consensus mechanism ensures rapid block production without losing miner participation. Uncle block rewards:
- Encourage miners to continue mining even after a "near-miss."
- Prevent chain splits by keeping computational power distributed.
6. Uncle Blocks vs. Bitcoin’s Orphan Blocks
Bitcoin does not reward orphan blocks, meaning that miners who solve a block that does not get included receive no rewards. This increases mining centralization, as only miners with the fastest network propagation times have an advantage.
Feature | Ethereum (Uncle Blocks) | Bitcoin (Orphan Blocks) |
---|---|---|
Reward for Stale Blocks? | ✅ Yes, uncle blocks receive rewards. | ❌ No, orphaned blocks receive nothing. |
Block Time | ~12-15 seconds | ~10 minutes |
Impact on Decentralization | Encourages small miners to continue mining. | Larger mining pools have an advantage. |
Ethereum’s uncle block model makes mining more inclusive and distributed, whereas Bitcoin’s orphan block approach favors large mining operations.
7. How to Retrieve Uncle Block Data
To check whether a block contains uncle references, developers can use ethers.js.
Example: Fetching Uncle Blocks Using ethers.js
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const getBlockWithUncles = async (blockNumber) => { const block = await provider.getBlock(blockNumber); console.log("Block Number:", block.number); console.log("Uncle Blocks:", block.uncles); }; getBlockWithUncles(15000000); </code></pre>
8. The Future of Uncle Blocks in Ethereum Post-Merge
With Ethereum’s transition to Proof of Stake (PoS) under The Merge, uncle blocks no longer exist.
Feature | Ethereum PoW (Before The Merge) | Ethereum PoS (After The Merge) |
---|---|---|
Uncle Blocks | Miners were rewarded for valid, stale blocks. | No uncle blocks exist in PoS. |
Block Competition | Multiple miners could solve blocks simultaneously. | A single validator is assigned each block proposal. |
Network Security | Miners contributed hash power. | Validators stake ETH to secure the network. |
In PoS, validators are randomly selected to propose blocks, eliminating the need for uncle block rewards. Instead, missed slots (failure to propose a block on time) result in penalties, ensuring network security.
Conclusion
Uncle blocks played a crucial role in Ethereum’s Proof of Work consensus mechanism by:
- Providing rewards for valid but unused blocks, preventing wasted mining effort.
- Ensuring small miners had a fair chance, reducing centralization risk.
- Enhancing overall network security, keeping more computational power engaged.
With Ethereum’s transition to Proof of Stake (PoS), uncle blocks are no longer necessary, but they remain an important part of Ethereum’s history in ensuring a decentralized and secure mining ecosystem.
Ethereum’s incentive model for uncle blocks is a critical mechanism designed to:
- Reduce mining centralization by allowing smaller miners to compete fairly.
- Increase network security by ensuring more honest participation in mining.
- Improve block propagation by rewarding miners for valid blocks that were not included in the canonical chain.
Unlike Bitcoin, where orphaned blocks receive no rewards, Ethereum compensates miners for uncle blocks, encouraging broader participation and reducing the risk of large mining pools monopolizing block production.
Understanding how uncle blocks work, how they are rewarded, and why they improve Ethereum’s decentralization and security is essential for analyzing Ethereum’s consensus model and network incentives.
1. What Are Uncle Blocks and Why Do They Occur?
An uncle block (or ommer block) is a valid block that was mined but not included in the main blockchain due to a competing block being accepted first.
Since Ethereum has short block times (~12-15 seconds per block), multiple miners can solve a block at nearly the same time. However, only one block can become part of the main chain, while others become uncle blocks.
Why Do Uncle Blocks Exist?
- Network latency – Some miners may receive block updates slower than others, causing temporary forks.
- Fast block production – Ethereum’s shorter block time increases the likelihood of simultaneous blocks.
- Block propagation delay – Some miners may mine a block before hearing about the latest valid block from another miner.
Instead of discarding uncle blocks, Ethereum rewards the miners who created them, ensuring their work is not wasted.
2. Incentive Model: How Are Uncle Blocks Rewarded?
Ethereum’s incentive model partially rewards uncle blocks to encourage miners to participate fairly, even if their block doesn’t get included in the main chain.
Who Gets Paid for Uncle Blocks?
- The miner who originally mined the uncle block.
- The miner who includes an uncle block reference in their new block.
3. Reward Calculation for Uncle Blocks
The reward for uncle blocks decreases based on their distance from the main chain.
Uncle Block Miner Reward
If the regular block reward is R
(e.g., 2 ETH per block), then an uncle block miner receives:
(7/8) × R
(87.5% of the full block reward).
Example:
If R = 2 ETH, then:
- The uncle block miner gets 1.75 ETH.
Main Block Miner’s Reward for Including an Uncle Block
The miner who includes an uncle block in their block gets:
(1/32) × R
per uncle block included.
Example:
- If R = 2 ETH, then the including miner gets 0.0625 ETH per uncle block.
- A single block can include up to 2 uncle blocks, meaning a miner could earn an extra 0.125 ETH.
4. How Uncle Block Rewards Reduce Mining Centralization
Without uncle block rewards, smaller miners would be at a disadvantage, because:
- Larger mining pools can spread block updates faster, reducing the chance of their blocks becoming uncles.
- Miners with weaker network connections would produce more orphaned blocks and lose rewards.
By rewarding uncle blocks, Ethereum ensures that miners still earn compensation even if their block didn’t make it to the main chain.
Impact on Decentralization
- Encourages solo and small miners to continue mining.
- Lowers the advantage of centralized mining pools that have lower orphan rates.
- Maintains a distributed network of miners, improving security.
5. How Uncle Blocks Improve Network Security
Ethereum’s uncle block incentive model improves security by:
1. Increasing Total Network Hash Power
Miners continue participating even if some of their blocks do not make it into the main chain, meaning more computational power secures the network.
2. Encouraging Honest Mining Participation
If orphaned blocks received no rewards, miners might collude with pools to reduce propagation times artificially. Uncle block rewards discourage such behavior.
3. Preventing Large Mining Pools from Monopolizing Block Production
- Without uncle block rewards, large mining pools would have an unfair advantage.
- Uncle blocks ensure smaller miners remain competitive, preventing a 51% attack scenario.
6. How Uncle Blocks Are Included in Ethereum Blocks
Each Ethereum block can reference up to two uncle blocks, allowing their miners to be rewarded.
Uncle block hashes are stored inside the block header, and Ethereum’s consensus rules ensure they:
- Were valid blocks.
- Were mined at roughly the same time as the main block.
- Are no more than six generations old.
To check whether a block contains uncle references, ethers.js can be used:
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const getBlockWithUncles = async (blockNumber) => { const block = await provider.getBlock(blockNumber); console.log("Block Number:", block.number); console.log("Uncle Blocks:", block.uncles); }; getBlockWithUncles(15000000); </code></pre>
7. Uncle Blocks vs. Bitcoin’s Orphan Blocks
Bitcoin does not reward orphan blocks, meaning miners who mine a block that doesn’t make it into the chain receive nothing. This increases centralization, as larger pools are less likely to lose blocks.
Feature | Ethereum (Uncle Blocks) | Bitcoin (Orphan Blocks) |
---|---|---|
Reward for Stale Blocks? | ✅ Yes, miners of uncle blocks receive rewards. | ❌ No, orphaned blocks receive nothing. |
Block Time | ~12-15 seconds | ~10 minutes |
Purpose | Reduces mining centralization and rewards near-miss blocks. | No incentives for orphan blocks, leading to higher centralization. |
Ethereum’s uncle block rewards make the mining ecosystem more inclusive and reduce reliance on large mining pools.
8. How Ethereum’s Switch to Proof of Stake (PoS) Affects Uncle Blocks
With Ethereum 2.0 (The Merge), Ethereum transitioned from Proof of Work (PoW) to Proof of Stake (PoS).
- Uncle blocks were removed because PoS eliminates block competition.
- Validators are chosen deterministically, preventing simultaneous block production.
- Missed block proposals are penalized, replacing the need for uncle block incentives.
Feature | PoW (Before The Merge) | PoS (After The Merge) |
---|---|---|
Uncle Blocks | Miners were rewarded for stale blocks. | Uncle blocks do not exist. |
Block Production | Miners compete to solve a block first. | Validators are assigned block proposals. |
Missed Rewards | Uncle blocks receive partial compensation. | Validators who miss a slot are penalized. |
While PoS removes uncle blocks, their past role in improving Ethereum’s mining fairness and decentralization was crucial.
Conclusion
Ethereum’s uncle block incentive model helped reduce mining centralization and improve network security by:
- Ensuring small miners still earn rewards even if their block isn’t included.
- Encouraging honest participation, increasing the overall network hash rate.
- Preventing large mining pools from gaining too much control over block production.
By compensating valid but stale blocks, Ethereum maintained a fairer, more decentralized Proof of Work system, improving network security until its transition to Proof of Stake, where uncle blocks are no longer needed.
Chapter 5
Exploring Ethereum Data & Tools
Understanding Ethereum in practice requires the ability to inspect blockchain data, interact with smart contracts, and test applications in a safe environment. Ethereum provides multiple tools and services that allow developers and users to:
- Track transactions and contracts using block explorers like Etherscan.
- Generate and manage Ethereum wallets to sign transactions.
- Use test networks (testnets) for development and experimentation without using real ETH.
By mastering these tools, developers can debug transactions, interact with smart contracts, and build decentralized applications (dApps) more efficiently.
1. Block Explorers: Viewing Ethereum Data
A block explorer is a web tool that allows users to view real-time blockchain activity, including transactions, blocks, smart contracts, and token transfers.
Popular Ethereum Block Explorers
- Etherscan – The most widely used Ethereum explorer.
- Blockscout – An open-source alternative.
- Ethplorer – Focuses on token analytics.
What Can You Do With a Block Explorer?
- Search for transactions by entering a transaction hash (TxID).
- Look up wallet addresses to see balances and transaction history.
- Inspect smart contracts to read and interact with deployed contracts.
- Monitor network activity such as gas prices, block times, and validator performance.
Example: Checking a Transaction on Etherscan
- Visit Etherscan.
- Enter a transaction hash in the search bar (e.g.,
0xabcdef123456...
). - Review transaction details, including:
- Sender and recipient addresses.
- Gas fee and transaction cost.
- Smart contract interaction details.
Fetching Ethereum Block Data Programmatically
Developers can retrieve block details using ethers.js.
<pre><code class=”language-js”> const { ethers } = require(“ethers”); const provider = new ethers.providers.JsonRpcProvider(“mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID”); const getBlockData = async (blockNumber) => { const block = await provider.getBlock(blockNumber); console.log(“Block Hash:”, block.hash); console.log(“Transactions:”, block.transactions); }; getBlockData(“latest”); </code></pre>
This script:
- Connects to Ethereum Mainnet via Infura.
- Fetches the latest block and prints transaction details.
2. Wallet Tools: Generating Addresses & Signing Transactions
An Ethereum wallet is essential for storing ETH, signing transactions, and interacting with dApps.
Types of Ethereum Wallets
Wallet Type | Examples | Use Case |
---|---|---|
Software Wallets | MetaMask, MyEtherWallet | Everyday transactions, dApp interactions. |
Hardware Wallets | Ledger, Trezor | Long-term storage, high-security transactions. |
Mobile Wallets | Trust Wallet, Argent | Mobile dApp access, DeFi transactions. |
Generating an Ethereum Address with ethers.js
Ethereum addresses are derived from private keys using cryptographic functions.
<pre><code class=”language-js”> const wallet = ethers.Wallet.createRandom(); console.log(“Ethereum Address:”, wallet.address); console.log(“Private Key:”, wallet.privateKey); </code></pre>
Signing a Transaction Programmatically
To send ETH from an EOA, a transaction must be signed with the private key.
<pre><code class=”language-js”> const provider = new ethers.providers.JsonRpcProvider(“mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID”); const wallet = new ethers.Wallet(“YOUR_PRIVATE_KEY”, provider); const transaction = { to: “0xRecipientAddress”, value: ethers.utils.parseEther(“0.1”), gasLimit: 21000 }; const sendTransaction = async () => { const tx = await wallet.sendTransaction(transaction); await tx.wait(); console.log(“Transaction Hash:”, tx.hash); }; sendTransaction(); </code></pre>
This script:
- Connects to Ethereum via Infura.
- Signs and broadcasts a transaction to send 0.1 ETH.
3. Test Networks: Safe Environments for Development
Ethereum provides testnets (test networks) where developers can experiment without using real ETH.
Popular Ethereum Testnets
Testnet | Purpose | Block Explorer |
---|---|---|
Goerli | Main testnet used for contract testing and staking. | goerli.etherscan.io |
Sepolia | A lightweight testnet replacing Ropsten. | sepolia.etherscan.io |
How to Get Free ETH on a Testnet
- Visit a faucet (e.g., Goerli Faucet).
- Enter your wallet address.
- Receive test ETH for free development use.
Connecting to a Testnet in ethers.js
<pre><code class=”language-js”> const provider = new ethers.providers.JsonRpcProvider(“goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID”); const checkBalance = async (address) => { const balance = await provider.getBalance(address); console.log(“ETH Balance:”, ethers.utils.formatEther(balance)); }; checkBalance(“0xYourTestnetAddress”); </code></pre>
This script:
- Connects to Goerli Testnet.
- Retrieves the balance of a wallet on the testnet.
4. Running an Ethereum Node: Full vs. Remote Nodes
Developers can interact with Ethereum via:
Node Type | Description | Examples |
---|---|---|
Full Node | Stores the complete blockchain and validates transactions. | Geth, Nethermind. |
Light Node | Stores only necessary blockchain data for fast syncing. | Geth (light mode). |
Remote Node | Connects to a provider without storing blockchain data. | Infura, Alchemy. |
Running an Ethereum Node with Geth (Full Node)
- Install Geth:
wget https://geth.ethereum.org/downloads/
- Start the node:
geth --syncmode full
- Attach to the console:
geth attach
Running a full node allows direct blockchain interaction without relying on third-party providers.
5. Debugging and Monitoring Transactions
When developing dApps, transaction debugging is crucial. Ethereum provides tools like:
1. Using Etherscan’s Debugging Features
- Revert reasons explain why a transaction failed.
- Gas estimations show if the sender had enough ETH.
2. Debugging with Hardhat’s Console
Developers can inspect contract behavior with Hardhat’s built-in console:
<pre><code class=”language-js”> npx hardhat console const contract = await ethers.getContractAt(“SimpleStorage”, “0xSmartContractAddress”); await contract.getValue(); </code></pre>
This allows developers to interact with contracts before deploying on the mainnet.
Conclusion
Exploring Ethereum’s data and tools is essential for understanding blockchain activity, developing smart contracts, and testing applications.
- Block explorers like Etherscan allow users to track transactions, contracts, and network health.
- Wallet tools enable users to generate addresses and sign transactions securely.
- Test networks provide a sandbox environment for development without real ETH.
- Running an Ethereum node provides full blockchain access for developers needing decentralized data.
- Debugging tools like Hardhat’s console and Etherscan logs help identify and fix transaction issues.
By mastering these tools, developers and users can efficiently interact with Ethereum, ensuring secure, transparent, and scalable blockchain applications.
Key Concepts
A block explorer is an essential tool for interacting with Ethereum’s blockchain, allowing users and developers to track transactions, inspect smart contracts, and analyze network activity in real-time.
Etherscan is the most widely used Ethereum block explorer. It provides:
- Transaction tracking – Viewing details of ETH transfers, token transactions, and gas fees.
- Smart contract inspection – Checking contract addresses, reading functions, and verifying source code.
- Network analysis – Monitoring blocks, validators, and gas prices.
By using Etherscan, developers and users can debug transactions, verify contract deployments, and ensure transparency on Ethereum.
1. What Is Etherscan and How Does It Work?
Etherscan is a public blockchain explorer that acts as a search engine for the Ethereum blockchain.
How Does Etherscan Work?
- Indexes Ethereum blockchain data and makes it searchable.
- Provides a graphical interface to explore transactions, blocks, and smart contracts.
- Allows users to interact with contracts by reading and writing functions.
Users can search for Ethereum data by entering a:
- Transaction hash (TxID)
- Wallet address
- Smart contract address
- Block number
2. Inspecting Transactions on Etherscan
A transaction on Ethereum contains critical information such as:
- Sender and recipient addresses
- Transaction fee and gas usage
- Smart contract interactions (if applicable)
How to Check a Transaction on Etherscan
- Go to Etherscan.io.
- Enter a transaction hash (TxID) in the search bar.
- Review transaction details, including:
- Status: Successful, Pending, or Failed.
- From and To Addresses: Sender and recipient.
- Gas Fees: The cost paid for execution.
- Input Data: If interacting with a contract, this field shows encoded function calls.
Example: Retrieving a Transaction’s Status Using ethers.js
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const checkTransaction = async (txHash) => { const tx = await provider.getTransaction(txHash); console.log("Transaction Hash:", tx.hash); console.log("From:", tx.from); console.log("To:", tx.to); console.log("Gas Used:", tx.gasLimit.toString()); }; checkTransaction("0xYourTransactionHash"); </code></pre>
This script:
- Fetches transaction details from Ethereum’s blockchain.
- Prints sender, recipient, and gas usage.
3. Inspecting Smart Contracts on Etherscan
Smart contracts deployed on Ethereum can be queried, verified, and interacted with directly on Etherscan.
Checking a Smart Contract on Etherscan
- Go to Etherscan.
- Enter the contract address in the search bar.
- View contract details, including:
- Contract Source Code: If verified, the Solidity code is publicly available.
- Read Contract: Check contract variables and stored data.
- Write Contract: Execute contract functions if permitted.
Example: Checking Contract State Using ethers.js
<pre><code class="language-js"> const contractAddress = "0xSmartContractAddress"; const contractABI = [ "function getValue() public view returns (uint256)" ]; const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const contract = new ethers.Contract(contractAddress, contractABI, provider); const checkContractValue = async () => { const value = await contract.getValue(); console.log("Stored Value:", value.toString()); }; checkContractValue(); </code></pre>
This script:
- Fetches the stored value in a SimpleStorage contract.
- Demonstrates how smart contracts store data on-chain.
4. Interacting With Smart Contracts on Etherscan
Etherscan provides a "Read/Write Contract" tab, allowing users to:
- Query on-chain variables (Read).
- Execute contract functions (Write).
Steps to Interact With a Contract on Etherscan
- Go to the contract page on Etherscan.
- Click on "Contract" → "Read Contract".
- View stored values, such as balances or token metadata.
- Click on "Write Contract" (Requires Wallet Connection).
- Execute functions like transferring tokens or updating values.
This feature helps debug contract interactions without needing a separate application.
5. Tracking Wallet Activity Using Etherscan
Users can monitor Ethereum wallets to:
- View transaction history (ETH transfers, token swaps).
- Check token balances (ERC-20 and ERC-721 tokens).
- Monitor gas fees paid over time.
Checking a Wallet on Etherscan
- Enter a wallet address in the search bar.
- Review ETH balance and tokens held.
- View transaction history and smart contract interactions.
Example: Fetching Wallet Balance Using ethers.js
<pre><code class="language-js"> const walletAddress = "0xYourEthereumAddress"; const checkBalance = async () => { const balance = await provider.getBalance(walletAddress); console.log("ETH Balance:", ethers.utils.formatEther(balance)); }; checkBalance(); </code></pre>
This script:
- Queries the blockchain for an EOA’s ETH balance.
6. Monitoring Ethereum Gas Prices Using Etherscan
Gas prices fluctuate based on network congestion. Users can check:
- Current gas fees for transactions.
- Priority fees required for faster processing.
Checking Gas Prices on Etherscan
- Visit Ethereum Gas Tracker.
- See low, average, and high gas fees.
- Estimate transaction costs for different operations.
Fetching Gas Prices Using ethers.js
<pre><code class="language-js"> const checkGasPrice = async () => { const gasPrice = await provider.getGasPrice(); console.log("Current Gas Price (Gwei):", ethers.utils.formatUnits(gasPrice, "gwei")); }; checkGasPrice(); </code></pre>
This script:
- Fetches real-time gas prices from Ethereum.
- Converts the value into Gwei, the standard gas unit.
7. Verifying Smart Contracts on Etherscan
Smart contract developers can verify their contracts on Etherscan to:
- Make the source code publicly viewable.
- Enable users to interact with the contract directly.
Steps to Verify a Smart Contract
- Deploy a contract using Hardhat or Truffle.
- Copy the contract's ABI and bytecode.
- Go to Etherscan and select "Verify & Publish Contract".
- Submit the contract source code.
- Confirm verification to make the contract readable.
Once verified, users can interact with the contract without using external tools.
8. Using Etherscan for Security Audits
Etherscan helps identify:
- Suspicious smart contracts (e.g., rug pulls, unauthorized mints).
- High-risk transactions (e.g., contract exploits).
- Wallet movements for large transactions.
By tracking contract interactions, users can avoid scams and malicious contracts.
Conclusion
Etherscan is a powerful tool for inspecting Ethereum transactions, contracts, and network activity.
- Users can track transactions, gas fees, and wallet balances.
- Developers can verify and interact with smart contracts.
- Security analysts can monitor blockchain activity for potential threats.
By mastering Etherscan, developers and users can better navigate the Ethereum ecosystem, debug transactions, and ensure transparency in decentralized applications.
Ethereum wallets are essential tools for storing, managing, and interacting with ETH, ERC-20 tokens, and smart contracts. They enable secure transactions by ensuring that only the owner of a private key can authorize operations.
Ethereum wallets come in various forms, each offering different levels of security, accessibility, and functionality. Choosing the right wallet depends on whether the user prioritizes security, convenience, or decentralized access.
This chapter explores the different types of Ethereum wallets, how they work, and how they enable secure transactions on the blockchain.
1. What Is an Ethereum Wallet?
An Ethereum wallet is a digital tool that allows users to:
- Store ETH and tokens securely.
- Sign and send transactions.
- Interact with smart contracts.
Each Ethereum wallet consists of:
- A Private Key – A secret key used to authorize transactions.
- A Public Address – A unique identifier that others use to send ETH and tokens.
How Ethereum Wallets Enable Secure Transactions
- Transactions must be signed with the private key, proving ownership.
- Each signature is unique, ensuring transactions cannot be forged.
- Wallets generate and manage private keys securely, preventing unauthorized access.
2. Types of Ethereum Wallets
Ethereum wallets are categorized based on:
- How they store private keys (Hot vs. Cold Wallets).
- Their mode of access (Software vs. Hardware).
Wallet Type | Example Wallets | Security Level | Best For |
---|---|---|---|
Hardware Wallets | Ledger, Trezor | 🔒🔒🔒 High | Long-term storage |
Software Wallets | MetaMask, MyEtherWallet | 🔒🔒 Medium | dApp interaction |
Mobile Wallets | Trust Wallet, Argent | 🔒🔒 Medium | On-the-go transactions |
Paper Wallets | Manually generated private keys | 🔒🔒🔒 High | Offline cold storage |
Multi-Signature Wallets | Gnosis Safe | 🔒🔒🔒 High | Shared accounts |
Each type offers a trade-off between security and convenience.
3. Hardware Wallets: Maximum Security for ETH Storage
Hardware wallets store private keys offline, making them immune to hacking attempts.
How Hardware Wallets Work
- The private key never leaves the device.
- Transactions are signed within the device and broadcasted securely.
Popular Hardware Wallets
Wallet | Features |
---|---|
Ledger Nano X | Supports multiple cryptocurrencies, Bluetooth connectivity. |
Trezor Model T | Open-source firmware, secure PIN protection. |
Why Use a Hardware Wallet?
✅ Best for long-term storage.
✅ Protects against phishing and malware attacks.
✅ Useful for high-value ETH holdings.
Example: Signing a Transaction with a Hardware Wallet
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const ledgerWallet = new ethers.Wallet("YOUR_LEDGER_PRIVATE_KEY", provider); const sendTransaction = async () => { const tx = await ledgerWallet.sendTransaction({ to: "0xRecipientAddress", value: ethers.utils.parseEther("0.5"), gasLimit: 21000 }); await tx.wait(); console.log("Transaction Hash:", tx.hash); }; sendTransaction(); </code></pre>
This script:
- Uses a Ledger hardware wallet to sign a transaction securely.
- Prevents private key exposure by keeping it on the device.
4. Software Wallets: Browser and Desktop Wallets
Software wallets are hot wallets that store private keys on a computer or mobile device.
Popular Software Wallets
Wallet | Type | Best Features |
---|---|---|
MetaMask | Browser & Mobile | dApp integration, Web3 support |
MyEtherWallet (MEW) | Web | Direct contract interactions |
Exodus | Desktop | Multi-asset wallet, intuitive UI |
How Software Wallets Enable Secure Transactions
- Encrypt private keys locally to prevent unauthorized access.
- Require user approval for every transaction.
- Integrate with dApps, allowing interaction with DeFi platforms.
Example: Sending ETH Using MetaMask
- Open MetaMask and connect it to a dApp.
- Click Send, enter the recipient’s address and amount.
- Confirm the transaction, signing it with the private key.
Using ethers.js to Sign a Transaction with MetaMask
<pre><code class="language-js"> const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const sendTransaction = async () => { const tx = await signer.sendTransaction({ to: "0xRecipientAddress", value: ethers.utils.parseEther("1.0"), gasLimit: 21000 }); console.log("Transaction Hash:", tx.hash); }; sendTransaction(); </code></pre>
This script:
- Uses MetaMask to sign and broadcast transactions.
5. Mobile Wallets: dApp-Friendly Crypto Wallets
Mobile wallets offer secure Ethereum transactions with QR scanning, multi-chain support, and dApp integration.
Popular Mobile Wallets
Wallet | Best Feature |
---|---|
Trust Wallet | Supports staking, NFTs, and in-wallet swaps. |
Argent | Social recovery for lost wallets. |
Rainbow Wallet | Focused on Ethereum dApps. |
Security Features of Mobile Wallets
- Private keys are encrypted and stored locally.
- Face ID and PIN protection.
- Supports DeFi and NFT marketplaces.
6. Paper Wallets: Cold Storage for Private Keys
A paper wallet is a printed document containing a private key and public address.
How Paper Wallets Work
- Users generate a key pair offline and write it down.
- The private key must be manually entered to sign transactions.
Security Risks of Paper Wallets
- Easily lost or destroyed (fire, water damage).
- Manually entering private keys exposes risk to keyloggers.
7. Multi-Signature Wallets: Secure Shared Accounts
Multi-signature (multi-sig) wallets require multiple private keys to approve transactions.
How Multi-Sig Wallets Work
- A threshold of signers (e.g., 2 out of 3) must approve a transaction.
- Used by DAOs and organizations for shared fund management.
Popular Multi-Sig Wallets
Wallet | Best Feature |
---|---|
Gnosis Safe | Highly secure, DAO-friendly. |
BitGo | Institutional-grade security. |
Example: Sending ETH with a Multi-Sig Wallet
<pre><code class="language-js"> const multiSigContract = new ethers.Contract("0xMultiSigAddress", contractABI, signer); const proposeTransaction = async () => { const tx = await multiSigContract.submitTransaction("0xRecipientAddress", ethers.utils.parseEther("1.0")); console.log("Transaction proposed:", tx.hash); }; proposeTransaction(); </code></pre>
This script proposes a multi-signature transaction that requires multiple approvals.
Conclusion
Ethereum wallets secure transactions by managing private keys, signing transactions, and providing user-friendly interfaces for dApp interactions.
- Hardware wallets provide the highest security for long-term storage.
- Software and mobile wallets enable daily transactions and DeFi interactions.
- Multi-signature wallets enhance shared security for organizations.
By choosing the right wallet, Ethereum users can balance security, convenience, and accessibility, ensuring safe and efficient blockchain transactions.
Ethereum test networks (testnets) are alternative blockchain environments that allow developers to experiment, test smart contracts, and simulate transactions without spending real ETH.
Testnets play a critical role in Ethereum development by:
- Providing a risk-free environment to deploy and debug smart contracts.
- Allowing dApp developers to test user interactions before launching on Mainnet.
- Simulating Ethereum’s network conditions (e.g., gas fees, block times) in a controlled setting.
Using testnets, developers can ensure that smart contracts function correctly, security vulnerabilities are identified, and application logic is optimized before deploying to Ethereum’s Mainnet.
1. What Are Ethereum Testnets?
Ethereum testnets are public blockchain environments that function similarly to the Ethereum Mainnet but use test ETH instead of real ETH.
Key Features of Testnets
✅ No real monetary risk – ETH on testnets has no real value.
✅ Identical EVM execution – Contracts behave the same way as they would on Mainnet.
✅ Decentralized validation – Some testnets use Proof of Stake (PoS) to mirror Ethereum’s Mainnet consensus.
✅ Faucets distribute free ETH, allowing developers to test transactions.
Testnets allow developers to experiment with Solidity smart contracts, dApps, and network interactions without incurring costs.
2. Major Ethereum Testnets and Their Use Cases
Ethereum currently supports multiple testnets, each serving different purposes.
Testnet | Consensus Mechanism | Block Explorer | Best For |
---|---|---|---|
Goerli | Proof of Stake (PoS) | goerli.etherscan.io | Smart contract testing, validator testing. |
Sepolia | Proof of Stake (PoS) | sepolia.etherscan.io | Lightweight, efficient contract testing. |
Goerli vs. Sepolia: Which Testnet Should You Use?
- Goerli: More decentralized, supports staking tests.
- Sepolia: More lightweight, ideal for dApp development.
Ropsten, Kovan, and Rinkeby testnets have been deprecated in favor of Goerli and Sepolia.
3. Why Are Testnets Essential for Ethereum Development?
1. Safe Environment for Smart Contract Testing
Developers can deploy and test contracts without financial loss before launching on Mainnet.
Example: Deploying a Smart Contract on Goerli
<pre><code class="language-js"> const { ethers } = require("ethers"); const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const contractFactory = new ethers.ContractFactory(contractABI, contractBytecode, wallet); const deployContract = async () => { const contract = await contractFactory.deploy(); await contract.deployed(); console.log("Contract deployed at:", contract.address); }; deployContract(); </code></pre>
This script:
- Deploys a Solidity smart contract on Goerli.
- Uses test ETH instead of real ETH.
2. Debugging and Optimizing Gas Costs
Gas fees are critical in Ethereum development. Testnets allow developers to estimate and optimize gas consumption before Mainnet deployment.
Example: Estimating Gas Costs on a Testnet
<pre><code class="language-js"> const contract = new ethers.Contract("0xContractAddress", contractABI, wallet); const estimateGas = async () => { const gasEstimate = await contract.estimateGas.setValue(42); console.log("Estimated Gas:", gasEstimate.toString()); }; estimateGas(); </code></pre>
This script:
- Simulates gas fees on a testnet.
- Helps optimize contract functions for lower gas consumption.
3. Testing dApp Functionality Before Mainnet Deployment
dApps must be tested under real network conditions before launching to users.
Developers use testnets to:
- Simulate high transaction volume.
- Test smart contract upgrades.
- Ensure UI and backend work correctly with blockchain data.
Example: Interacting With a Smart Contract on Sepolia
<pre><code class="language-js"> const provider = new ethers.providers.JsonRpcProvider("https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID"); const contract = new ethers.Contract("0xContractAddress", contractABI, provider); const fetchContractData = async () => { const data = await contract.getValue(); console.log("Stored Value:", data.toString()); }; fetchContractData(); </code></pre>
4. How Developers Can Use Testnets for Ethereum Development
Step 1: Setting Up a Testnet Connection
To interact with testnets, developers must connect their Ethereum wallets to a testnet RPC provider.
Example: Connecting MetaMask to Goerli
- Open MetaMask and go to Settings → Networks.
- Add a new network with the following:
- Network Name: Goerli
- RPC URL:
https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID
- Chain ID:
5
- Click Save and switch to Goerli.
Step 2: Getting Test ETH from a Faucet
Testnets require test ETH to simulate transactions.
- Visit a testnet faucet like:
- Goerli Faucet: goerlifaucet.com
- Sepolia Faucet: sepoliafaucet.com
- Enter your Ethereum address.
- Click Request Funds to receive free test ETH.
Step 3: Deploying and Testing a Smart Contract
Developers use Hardhat, Truffle, or Remix to deploy contracts.
Example: Deploying a Smart Contract Using Hardhat
<pre><code class="language-js"> const hre = require("hardhat"); async function main() { const Contract = await hre.ethers.getContractFactory("SimpleStorage"); const contract = await Contract.deploy(); await contract.deployed(); console.log("Contract deployed to:", contract.address); } main(); </code></pre>
This script:
- Deploys a contract to Goerli or Sepolia.
- Uses test ETH for deployment.
5. How Testnets Improve Ethereum’s Ecosystem
Benefit | How It Helps Developers |
---|---|
Smart Contract Testing | Ensures contracts function correctly before Mainnet deployment. |
Gas Fee Optimization | Allows developers to estimate and reduce gas costs. |
dApp UI/Backend Testing | Tests frontend blockchain interactions before user release. |
Validator and Node Testing | Helps Ethereum node operators test staking setups. |
6. Monitoring Transactions and Contracts on Testnets
Developers use testnet block explorers to inspect transactions.
Testnet | Block Explorer |
---|---|
Goerli | goerli.etherscan.io |
Sepolia | sepolia.etherscan.io |
Checking a Testnet Transaction
- Visit Goerli Etherscan.
- Enter the transaction hash.
- View details such as:
- Sender and recipient addresses.
- Gas fee and execution status.
Fetching Testnet Block Data Using ethers.js
<pre><code class="language-js"> const getTestnetBlock = async () => { const block = await provider.getBlock("latest"); console.log("Block Number:", block.number); console.log("Block Hash:", block.hash); }; getTestnetBlock(); </code></pre>
Conclusion
Ethereum testnets are essential for blockchain development because they:
- Provide a risk-free environment for smart contract testing.
- Allow developers to debug transactions and optimize gas costs.
- Ensure dApps function correctly before launching on Mainnet.
By using Goerli and Sepolia, developers can build secure, efficient, and well-tested decentralized applications, reducing the risks of Mainnet deployment failures and costly errors.