Learning Center > Blockchain & Web3 Development

Ethereum Basics

By understanding Ethereum’s account-based system, the Ethereum Virtual Machine (EVM), and the role of gas in powering transactions, learners can grasp how Ethereum supports a thriving ecosystem of decentralized applications (dApps).

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

FeatureBitcoinEthereum
Primary Use CaseDigital currencySmart contracts and dApps
Consensus MechanismProof of Work (PoW) → Proof of Stake (PoS)Proof of Stake (PoS)
Transaction ModelUTXO (Unspent Transaction Output)Account-based
Block Time~10 minutes~12-15 seconds
Native CurrencyBTCETH
Smart ContractsLimited scriptingFully 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>

ModelAdvantagesDisadvantages
UTXOEnhanced privacy, parallel processingMore complex tracking
Account-BasedSimpler, allows smart contractsHigher 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 ApplicationFunctionExample Protocols
Decentralized Exchanges (DEXs)Peer-to-peer tradingUniswap, SushiSwap
Lending & BorrowingCollateralized loansAave, Compound
Yield FarmingEarning rewards for providing liquidityYearn 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 MechanismBitcoin (PoW)Ethereum (PoS)
Energy ConsumptionHighLow
Block Creation Time10 minutes~12 seconds
Security ModelMiners solve cryptographic puzzlesValidators 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 UpgradeExpected Benefit
ShardingSplits blockchain into smaller parts to improve speed.
Layer 2 Solutions (Optimistic & ZK Rollups)Reduces fees and increases transaction throughput.
Account AbstractionEnhances 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

FeatureBitcoin (UTXO Model)Ethereum (Account Model)
Tracking FundsUses unspent transaction outputsUses account balances
Transaction TypeEach transaction spends specific UTXOsEach transaction modifies balances directly
Change HandlingRequires a change output if spending more than requiredNo change needed; balance updates directly
PrivacyBetter privacy; transactions can’t be linked easilyLower privacy; account balances are publicly visible
Smart ContractsLimited scripting, mainly for transactionsFully programmable smart contracts
ScalabilityHarder to scale due to complex UTXO trackingEasier 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 stored value 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 TypeFunctionExample Protocols
Decentralized Finance (DeFi)Lending, trading, yield farmingUniswap, Aave, Compound
Non-Fungible Tokens (NFTs)Digital asset ownershipOpenSea, Rarible, Axie Infinity
Gaming & MetaverseBlockchain-based gamesDecentraland, The Sandbox
DAOs (Decentralized Autonomous Organizations)Community governanceMakerDAO, 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

RiskDescriptionExample Exploits
Reentrancy AttacksRepeated external calls drain funds.The DAO Hack (2016)
Integer OverflowLarge numbers break contract logic.Smart contract errors in early ERC-20 tokens.
Front-RunningAttackers manipulate pending transactions.MEV (Miner Extractable Value) exploits.

Best Practices for Secure Smart Contracts

  1. Use Secure Libraries – Use OpenZeppelin’s audited contracts.
  2. 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.

UpgradeImpact
Layer 2 Rollups (Optimistic & ZK Rollups)Faster transactions, lower fees
Account AbstractionSimplifies smart contract wallets
EIP-1559Improves 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

FeatureProof of Work (PoW)Proof of Stake (PoS)
Validation MethodMining (solving cryptographic puzzles)Staking ETH and validating transactions
Energy ConsumptionVery high (relies on computational power)99.95% lower than PoW
Block Creation Time~12–14 seconds~12 seconds
Security ModelHigh cost to attack due to hardware requirementsSlashing penalties prevent malicious behavior
ScalabilityLimited 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.

NetworkAnnual 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 UpgradeExpected Benefit
ShardingSplits blockchain into smaller parts to improve transaction speed.
Layer 2 Rollups (Optimistic & ZK Rollups)Reduces gas fees and improves transaction throughput.
Account AbstractionEnhances 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:

  1. 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.
  2. 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

FeatureExternally Owned Account (EOA)Contract Account
Controlled ByPrivate keySmart contract code
Can Initiate Transactions?YesNo
Stores ETH?YesYes (if programmed to)
Executes Smart Contracts?YesOnly when triggered by an EOA or another contract
Gas PaymentPaid by the senderPaid 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:

  1. Recipient address – Where ETH or contract data is sent.
  2. Amount of ETH (if applicable) – The amount of ETH being transferred.
  3. Gas limit – The maximum amount of gas the sender is willing to pay for the transaction to be processed.
  4. 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:

  1. The EOA creates a transaction, specifying the contract address and function to call.
  2. The transaction is signed and broadcasted.
  3. The Ethereum Virtual Machine (EVM) executes the function, modifying the contract’s state.
  4. 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:

  1. Create a transaction request, specifying the recipient, ETH amount, gas limit, and contract data (if applicable).
  2. Sign the transaction using its private key, proving ownership and authorization.
  3. 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

  1. User (EOA owner) initiates a transaction using a wallet or script.
  2. EOA signs the transaction with its private key to prove authenticity.
  3. Transaction is broadcasted to the Ethereum network.
  4. Ethereum nodes validate the transaction and include it in a block.
  5. 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:

  1. A simple ETH transfer from one EOA to another.
  2. A smart contract interaction, calling a function within a deployed contract.
  3. 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

  1. The sender EOA creates a transaction specifying:
    • The recipient address.
    • The amount of ETH to send.
    • A gas limit to pay for network fees.
  2. The sender signs the transaction using their private key.
  3. The transaction is broadcasted to the network.
  4. Ethereum miners/validators verify and confirm the transaction in a block.
  5. 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

  1. 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).
  2. The sender signs the transaction using their private key.
  3. The transaction is broadcasted to the Ethereum network.
  4. The Ethereum Virtual Machine (EVM) executes the function within the smart contract.
  5. 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

  1. 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).
  2. The sender signs and broadcasts the transaction.
  3. The transaction is confirmed on the blockchain, and Ethereum assigns the contract a unique address.
  4. 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.

FunctionEOA Role
Sending ETHEOAs initiate ETH transfers to other EOAs or smart contracts.
Calling Smart ContractsEOAs trigger contract execution (DeFi, NFTs, DAOs).
Deploying ContractsEOAs 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

RiskDescriptionExample Exploits
Reentrancy AttacksMalicious contracts repeatedly call functions before the first execution completes.The DAO Hack (2016)
Integer OverflowLarge numbers break contract logic.Early ERC-20 token exploits
Access Control IssuesPoorly 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.

UpgradeImpact
Layer 2 RollupsReduces gas fees for contract execution
EIP-1559Improves 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.

UpgradeImpact
Account Abstraction (EIP-4337)Allows EOAs to function like smart contract wallets
Layer 2 Scaling (Rollups)Reduces gas fees for contract interactions
Gas SponsorshipEnables 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

  1. Transaction is sent from an EOA, triggering the contract.
  2. The transaction is processed by the EVM, which reads the function’s bytecode.
  3. Opcodes are executed step by step, modifying stack, memory, and storage.
  4. Gas is consumed for each operation, ensuring computational fairness and preventing spam.
  5. 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:

  1. Pushes values onto the stack.
  2. Executes the ADD operation.
  3. 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:

  1. Converting high-level Solidity code into an Abstract Syntax Tree (AST).
  2. Generating EVM opcodes from the AST.
  3. 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.

UpgradeImpact
EIP-1559Improves gas fee predictability and reduces congestion.
Optimistic Rollups & ZK-RollupsMoves 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.

MethodProsCons
Running a Full NodeComplete control, local data accessRequires high storage, bandwidth, and maintenance
Using InfuraEasy, scalable, and fast API accessRelies 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.

ComponentMeaning
https://mainnet.infura.ioInfura’s Ethereum Mainnet gateway
/v3/API version 3
YOUR_INFURA_PROJECT_IDA 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

  1. Go to Infura’s Website: https://infura.io/
  2. Sign up for a free account.
  3. Create a new project.
  4. Copy the "PROJECT ID" from the project settings.
  5. 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:

NetworkEndpoint
Ethereum Mainnethttps://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
Goerli Testnethttps://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID
Sepolia Testnethttps://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:

ProviderFeatures
AlchemyHigh-speed, scalable Ethereum API
QuickNodeLow-latency blockchain access
AnkrDecentralized 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:

  1. Transaction Processing: How the EVM receives and validates transactions.
  2. Bytecode Execution: How Solidity code is compiled and executed using EVM opcodes.
  3. Stack and Memory Operations: How the EVM processes instructions in a stack-based architecture.
  4. Gas Consumption: How the EVM prevents infinite execution with gas fees.
  5. 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

  1. Instructions push data onto the stack.
  2. Opcodes process data on the stack.
  3. 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

OpcodeGas Cost
ADD3 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 slot 0x01 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:

  1. Returns the result to the caller (if applicable).
  2. 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

StepProcess
1. Transaction ProcessingAn EOA sends a transaction to a smart contract.
2. Bytecode ExecutionSolidity code is compiled into EVM bytecode and executed.
3. Stack and Memory OperationsData is processed using the stack and memory.
4. Gas ConsumptionEach operation deducts gas, preventing infinite execution.
5. State ChangesStorage updates modify the blockchain state.
6. Finalizing ExecutionThe 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.

ModifierDescription
publicAnyone can call the function.
privateOnly the contract itself can call the function.
internalOnly the contract and derived contracts can access the function.
externalCan 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

  1. Parsing – The Solidity compiler (solc) converts the code into an Abstract Syntax Tree (AST).
  2. Bytecode Generation – The compiler converts AST into EVM opcodes.
  3. 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

  1. Before execution, the sender specifies a gas limit.
  2. If execution exceeds the gas limit, the transaction fails and reverts.
  3. 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

  1. Proxy Contracts – Instead of modifying a contract, developers deploy a new version and use a proxy contract to redirect calls to the updated logic.
  2. Self-Destruct Mechanism – Some contracts include a selfdestruct() function to remove the contract and allow redeployment.
  3. 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:

  1. Improving network security by reducing orphan blocks.
  2. Providing incentives to miners who contribute computational power but miss inclusion in the main chain.
  3. 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

ComponentDescription
Block HeaderContains metadata such as the parent block hash, timestamp, and difficulty.
TransactionsA list of all transactions included in the block.
State RootThe Merkle root hash representing the global state after executing transactions.
Receipts RootA 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:

  1. Be a valid block mined according to Ethereum’s consensus rules.
  2. Not be the canonical block in the chain.
  3. Be referenced within the next six blocks after it was mined.
  4. 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.

FeatureEthereum (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
PurposeReduces 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”.

FeatureEthereum PoW (Before The Merge)Ethereum PoS (After The Merge)
Uncle BlocksMiners were rewarded for valid, stale blocks.No uncle blocks in PoS.
Missed SlotsNot 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:

  1. Block Header – Contains metadata such as timestamps, difficulty, and references to previous blocks.
  2. Transactions List – Stores executed transactions and contract interactions.
  3. 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

FieldDescription
Parent HashThe hash of the previous block, linking blocks together in a chain.
Uncle HashA reference to valid, but not included, uncle blocks.
State RootThe Merkle root hash representing the entire Ethereum state.
Transactions RootA Merkle root of all transactions included in this block.
Receipts RootA Merkle root summarizing all transaction receipts.
Block NumberThe sequential identifier for the block.
TimestampThe 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 GasThe 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:

FieldDescription
NonceA counter that ensures transactions execute in order.
Gas PriceThe fee the sender is willing to pay for execution.
Gas LimitThe maximum gas the sender is willing to spend.
Recipient AddressThe EOA or contract the transaction is directed to.
ValueThe amount of ETH being transferred.
DataContains smart contract function calls and parameters.
V, R, SCryptographic 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 TypeEthereum’s Protection Mechanism
Double SpendingBlocks reference previous state roots, preventing modification of past transactions.
Sybil AttacksValidators in PoS must stake ETH, making attacks costly.
Replay AttacksNonce values enforce transaction order and prevent replays.
Infinite ExecutionGas 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:

  1. Reduce the impact of network latency by rewarding blocks that were valid but not included in the main chain.
  2. Improve decentralization by making mining rewards more accessible to smaller miners.
  3. 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:

  1. Network Latency – Some nodes receive new blocks slightly later than others, leading to temporary chain forks.
  2. Propagation Delays – Large networks take time to sync, so some miners unknowingly build on outdated data.
  3. 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:

  1. The miner who originally mined the uncle block.
  2. 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.

FeatureEthereum (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 DecentralizationEncourages 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.

FeatureEthereum PoW (Before The Merge)Ethereum PoS (After The Merge)
Uncle BlocksMiners were rewarded for valid, stale blocks.No uncle blocks exist in PoS.
Block CompetitionMultiple miners could solve blocks simultaneously.A single validator is assigned each block proposal.
Network SecurityMiners 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:

  1. Reduce mining centralization by allowing smaller miners to compete fairly.
  2. Increase network security by ensuring more honest participation in mining.
  3. 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?

  1. The miner who originally mined the uncle block.
  2. 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.

FeatureEthereum (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
PurposeReduces 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.
FeaturePoW (Before The Merge)PoS (After The Merge)
Uncle BlocksMiners were rewarded for stale blocks.Uncle blocks do not exist.
Block ProductionMiners compete to solve a block first.Validators are assigned block proposals.
Missed RewardsUncle 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:

  1. Track transactions and contracts using block explorers like Etherscan.
  2. Generate and manage Ethereum wallets to sign transactions.
  3. 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

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

  1. Visit Etherscan.
  2. Enter a transaction hash in the search bar (e.g., 0xabcdef123456...).
  3. 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 TypeExamplesUse Case
Software WalletsMetaMask, MyEtherWalletEveryday transactions, dApp interactions.
Hardware WalletsLedger, TrezorLong-term storage, high-security transactions.
Mobile WalletsTrust Wallet, ArgentMobile 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

TestnetPurposeBlock Explorer
GoerliMain testnet used for contract testing and staking.goerli.etherscan.io
SepoliaA lightweight testnet replacing Ropsten.sepolia.etherscan.io

How to Get Free ETH on a Testnet

  1. Visit a faucet (e.g., Goerli Faucet).
  2. Enter your wallet address.
  3. 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 TypeDescriptionExamples
Full NodeStores the complete blockchain and validates transactions.Geth, Nethermind.
Light NodeStores only necessary blockchain data for fast syncing.Geth (light mode).
Remote NodeConnects to a provider without storing blockchain data.Infura, Alchemy.

Running an Ethereum Node with Geth (Full Node)

  1. Install Geth:
     
    wget https://geth.ethereum.org/downloads/
  2. Start the node:
     
    geth --syncmode full
  3. 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:

  1. Transaction tracking – Viewing details of ETH transfers, token transactions, and gas fees.
  2. Smart contract inspection – Checking contract addresses, reading functions, and verifying source code.
  3. 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

  1. Go to Etherscan.io.
  2. Enter a transaction hash (TxID) in the search bar.
  3. 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

  1. Go to Etherscan.
  2. Enter the contract address in the search bar.
  3. 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

  1. Go to the contract page on Etherscan.
  2. Click on "Contract" → "Read Contract".
  3. View stored values, such as balances or token metadata.
  4. Click on "Write Contract" (Requires Wallet Connection).
  5. 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

  1. Enter a wallet address in the search bar.
  2. Review ETH balance and tokens held.
  3. 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

  1. Visit Ethereum Gas Tracker.
  2. See low, average, and high gas fees.
  3. 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

  1. Deploy a contract using Hardhat or Truffle.
  2. Copy the contract's ABI and bytecode.
  3. Go to Etherscan and select "Verify & Publish Contract".
  4. Submit the contract source code.
  5. 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:

  1. A Private Key – A secret key used to authorize transactions.
  2. 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 TypeExample WalletsSecurity LevelBest For
Hardware WalletsLedger, Trezor🔒🔒🔒 HighLong-term storage
Software WalletsMetaMask, MyEtherWallet🔒🔒 MediumdApp interaction
Mobile WalletsTrust Wallet, Argent🔒🔒 MediumOn-the-go transactions
Paper WalletsManually generated private keys🔒🔒🔒 HighOffline cold storage
Multi-Signature WalletsGnosis Safe🔒🔒🔒 HighShared 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

WalletFeatures
Ledger Nano XSupports multiple cryptocurrencies, Bluetooth connectivity.
Trezor Model TOpen-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

WalletTypeBest Features
MetaMaskBrowser & MobiledApp integration, Web3 support
MyEtherWallet (MEW)WebDirect contract interactions
ExodusDesktopMulti-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

  1. Open MetaMask and connect it to a dApp.
  2. Click Send, enter the recipient’s address and amount.
  3. 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

WalletBest Feature
Trust WalletSupports staking, NFTs, and in-wallet swaps.
ArgentSocial recovery for lost wallets.
Rainbow WalletFocused 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

WalletBest Feature
Gnosis SafeHighly secure, DAO-friendly.
BitGoInstitutional-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:

  1. Providing a risk-free environment to deploy and debug smart contracts.
  2. Allowing dApp developers to test user interactions before launching on Mainnet.
  3. 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.

TestnetConsensus MechanismBlock ExplorerBest For
GoerliProof of Stake (PoS)goerli.etherscan.ioSmart contract testing, validator testing.
SepoliaProof of Stake (PoS)sepolia.etherscan.ioLightweight, 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

  1. Open MetaMask and go to Settings → Networks.
  2. Add a new network with the following:
    • Network Name: Goerli
    • RPC URL: https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID
    • Chain ID: 5
  3. Click Save and switch to Goerli.

Step 2: Getting Test ETH from a Faucet

Testnets require test ETH to simulate transactions.

  1. Visit a testnet faucet like:
  2. Enter your Ethereum address.
  3. 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

BenefitHow It Helps Developers
Smart Contract TestingEnsures contracts function correctly before Mainnet deployment.
Gas Fee OptimizationAllows developers to estimate and reduce gas costs.
dApp UI/Backend TestingTests frontend blockchain interactions before user release.
Validator and Node TestingHelps Ethereum node operators test staking setups.

6. Monitoring Transactions and Contracts on Testnets

Developers use testnet block explorers to inspect transactions.

TestnetBlock Explorer
Goerligoerli.etherscan.io
Sepoliasepolia.etherscan.io

Checking a Testnet Transaction

  1. Visit Goerli Etherscan.
  2. Enter the transaction hash.
  3. 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.

Ready to test your knowledge?

Jump to Quiz