Bird
Raised Fist0
Blockchain / Solidityprogramming~10 mins

Web3.js vs ethers.js in Blockchain / Solidity - Visual Side-by-Side Comparison

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Web3.js vs ethers.js
Start
Choose Library
Web3.js
Connect to Ethereum
Send Transactions
Get Blockchain Data
End
This flow shows choosing between Web3.js and ethers.js libraries, then connecting to Ethereum, interacting with contracts, sending transactions, and getting blockchain data.
Execution Sample
Blockchain / Solidity
import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_API_KEY');
const blockNumber = await provider.getBlockNumber();
console.log(`Current block number: ${blockNumber}`);
This code connects to Ethereum mainnet using ethers.js and prints the current block number.
Execution Table
StepActionEvaluationResult
1Import ethers libraryethers importedethers object available
2Create provider with Infura URLprovider createdprovider connected to Ethereum mainnet
3Call getBlockNumber()await provider.getBlockNumber()fetches latest block number
4Print block numberconsole.log outputCurrent block number: 17500000 (example)
5EndNo more codeProgram ends
💡 Program ends after printing the current block number.
Variable Tracker
VariableStartAfter Step 2After Step 3Final
ethersundefinedethers objectethers objectethers object
providerundefinedJsonRpcProvider instanceJsonRpcProvider instanceJsonRpcProvider instance
blockNumberundefinedundefined17500000 (example)17500000 (example)
Key Moments - 3 Insights
Why do we need a provider in ethers.js?
The provider connects your code to the Ethereum network to read blockchain data, as shown in step 2 and 3 of the execution_table.
What is the difference between Web3.js and ethers.js in usage?
Both connect to Ethereum and interact with contracts, but ethers.js uses simpler, promise-based calls and better defaults, making it easier to use as seen in the sample code.
Why do we use await with getBlockNumber()?
Because getBlockNumber() is asynchronous and returns a promise, we use await to wait for the result before continuing, as shown in step 3.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of 'blockNumber' after step 3?
Aundefined
B17500000 (example)
Cethers object
DJsonRpcProvider instance
💡 Hint
Check the variable_tracker row for 'blockNumber' after step 3.
At which step does the program connect to the Ethereum network?
AStep 2
BStep 3
CStep 1
DStep 4
💡 Hint
Look at the execution_table action descriptions for when the provider is created.
If we replaced ethers.js with Web3.js, which part of the code would change most?
AVariable names only
BConsole.log statement
CImport statement and provider creation
DNo changes needed
💡 Hint
Consider how the library import and connection setup differ between ethers.js and Web3.js.
Concept Snapshot
Web3.js and ethers.js are JavaScript libraries to interact with Ethereum.
ethers.js uses promise-based calls and simpler syntax.
Create a provider to connect to Ethereum network.
Use provider methods to read blockchain data.
Use async/await to handle asynchronous calls.
Choose ethers.js for easier and modern usage.
Full Transcript
This visual execution compares Web3.js and ethers.js libraries for Ethereum interaction. The flow starts with choosing a library, then connecting to Ethereum via a provider, interacting with smart contracts, sending transactions, and reading blockchain data. The sample code shows ethers.js usage: importing the library, creating a JsonRpcProvider connected to Infura, calling getBlockNumber asynchronously, and printing the current block number. The execution table traces each step, showing variable states and actions. Key moments clarify why a provider is needed, differences in usage, and the role of async/await. The quiz tests understanding of variable values, connection steps, and differences between libraries. The snapshot summarizes key points for quick reference.

Practice

(1/5)
1. Which of the following is a key difference between Web3.js and ethers.js?
easy
A. ethers.js is a backend-only library, Web3.js is frontend-only.
B. Web3.js only works with Bitcoin, ethers.js only with Ethereum.
C. ethers.js cannot send transactions, Web3.js can.
D. Web3.js is larger and older, while ethers.js is lighter and simpler.

Solution

  1. Step 1: Understand library origins

    Web3.js is an older, larger library designed for Ethereum interaction.
  2. Step 2: Compare library features

    ethers.js is newer, designed to be lightweight and simpler to use.
  3. Final Answer:

    Web3.js is larger and older, while ethers.js is lighter and simpler. -> Option D
  4. Quick Check:

    Library size and age = A [OK]
Hint: Remember: Web3.js is big and old; ethers.js is small and new [OK]
Common Mistakes:
  • Thinking ethers.js only works on backend
  • Confusing blockchain support (Bitcoin vs Ethereum)
  • Believing ethers.js can't send transactions
2. Which of the following is the correct way to create a provider using ethers.js?
easy
A. const provider = new ethers.providers.JsonRpcProvider();
B. const provider = new Web3.providers.HttpProvider();
C. const provider = new ethers.Web3Provider();
D. const provider = new Web3.eth.JsonRpcProvider();

Solution

  1. Step 1: Recall ethers.js provider syntax

    ethers.js uses ethers.providers.JsonRpcProvider() to create a JSON RPC provider.
  2. Step 2: Identify correct syntax

    const provider = new ethers.providers.JsonRpcProvider(); matches the correct ethers.js syntax; others mix Web3.js or incorrect classes.
  3. Final Answer:

    const provider = new ethers.providers.JsonRpcProvider(); -> Option A
  4. Quick Check:

    ethers.js provider creation = D [OK]
Hint: ethers.js uses ethers.providers.JsonRpcProvider() [OK]
Common Mistakes:
  • Mixing Web3.js and ethers.js syntax
  • Using Web3 classes with ethers.js
  • Incorrect capitalization or namespaces
3. What will be the output of this ethers.js code snippet?
const ethers = require('ethers');
const provider = new ethers.providers.JsonRpcProvider();
(async () => {
  const blockNumber = await provider.getBlockNumber();
  console.log(blockNumber);
})();
medium
A. An error because getBlockNumber() is not a function.
B. Undefined because provider is not initialized.
C. The current Ethereum block number as a number.
D. A string 'blockNumber' printed to console.

Solution

  1. Step 1: Understand provider and method

    The JsonRpcProvider connects to Ethereum and getBlockNumber() returns the latest block number as a number.
  2. Step 2: Analyze async function output

    The code logs the block number to console, so output is a number representing current block.
  3. Final Answer:

    The current Ethereum block number as a number. -> Option C
  4. Quick Check:

    getBlockNumber() returns number [OK]
Hint: getBlockNumber() returns a number, not error or string [OK]
Common Mistakes:
  • Expecting a string instead of number
  • Thinking getBlockNumber() is missing
  • Assuming provider is uninitialized
4. Identify the error in this Web3.js code snippet:
const Web3 = require('web3');
const web3 = new Web3();
(async () => {
  const balance = await web3.eth.getBalance('0x123...');
  console.log(balance);
})();
medium
A. Missing provider URL when creating Web3 instance.
B. getBalance() is not an async function.
C. The address format is incorrect.
D. console.log cannot print balance.

Solution

  1. Step 1: Check Web3 instance creation

    Web3 requires a provider URL (like HTTP or WebSocket) when instantiated to connect to Ethereum.
  2. Step 2: Identify missing provider

    The code creates new Web3() without a provider, so calls like getBalance will fail.
  3. Final Answer:

    Missing provider URL when creating Web3 instance. -> Option A
  4. Quick Check:

    Web3 needs provider URL [OK]
Hint: Always pass provider URL to Web3 constructor [OK]
Common Mistakes:
  • Thinking getBalance is not async
  • Assuming address format is wrong
  • Believing console.log can't print balance
5. You want to send a transaction using ethers.js and wait for it to be mined. Which code snippet correctly does this?
hard
A. const tx = await provider.sendTransaction(txData); await tx.wait();
B. const tx = await signer.sendTransaction(txData); await tx.wait(); console.log('Mined:', tx.hash);
C. const tx = signer.sendTransaction(txData); console.log('Mined:', tx.hash);
D. const tx = await signer.send(txData); await tx.wait();

Solution

  1. Step 1: Identify correct method to send transaction

    In ethers.js, signer.sendTransaction() sends a transaction and returns a transaction response.
  2. Step 2: Wait for transaction mining

    Calling tx.wait() waits for the transaction to be mined before proceeding.
  3. Step 3: Confirm correct usage

    const tx = await signer.sendTransaction(txData; await tx.wait(); console.log('Mined:', tx.hash); correctly awaits sending, then waits for mining, then logs the hash.
  4. Final Answer:

    const tx = await signer.sendTransaction(txData); await tx.wait(); console.log('Mined:', tx.hash); -> Option B
  5. Quick Check:

    sendTransaction + wait() = C [OK]
Hint: Use sendTransaction() then wait() to confirm mining [OK]
Common Mistakes:
  • Not awaiting sendTransaction()
  • Using provider instead of signer to send
  • Calling non-existent send() method