Last Updated: December 18, 2025
┌─────────────────────────────────────────────────────────────────┐
│ YOUR BROWSER │
│ │
│ ┌──────────────────┐ ┌─────────────────────┐ │
│ │ React App │ │ MetaMask │ │
│ │ (Frontend) │◄────────────►│ (Wallet Plugin) │ │
│ │ │ Requests │ │ │
│ │ - Displays UI │ Approval │ - Holds Private │ │
│ │ - Shows Balance │ │ Key │ │
│ │ - Buttons │ │ - Signs Txs │ │
│ └────────┬─────────┘ └──────────┬──────────┘ │
│ │ │ │
│ │ Uses ethers.js library │ │
│ │ to communicate │ │
│ └───────────────┬───────────────────┘ │
│ │ │
└───────────────────────────┼──────────────────────────────────────┘
│
│ JSON-RPC Calls
│ (Web3 Protocol)
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ETHEREUM BLOCKCHAIN │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Your Smart Contract (MessageBoard.sol) │ │
│ │ Address: 0xabc123... (generated when deployed) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ State (Permanent Storage) │ │ │
│ │ │ • message = "Hello World" │ │ │
│ │ │ • lastWriter = 0x456... │ │ │
│ │ │ • lastUpdated = 1702857600 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Functions (Executable Code) │ │ │
│ │ │ • setMessage() ← Costs Gas │ │ │
│ │ │ • getMessage() ← Free (view only) │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
What you do: Click "Connect Wallet" button
User clicks button
↓
React calls MetaMask
↓
MetaMask popup appears: "Connect to this site?"
↓
User approves
↓
MetaMask shares your PUBLIC address (0x123...)
↓
React displays: "Connected: 0x123..."
Important: MetaMask NEVER shares your private key. It only gives the app permission to:
- See your address
- Request you to sign transactions (you approve each one)
What you do: App shows your ETH balance automatically
React has your address (0x123...)
↓
ethers.js sends request to Ethereum:
"What's the balance of 0x123...?"
↓
Blockchain responds: "2.5 ETH"
↓
React displays: "Balance: 2.5 ETH"
Cost: FREE (reading blockchain data doesn't change anything)
What you do: Enter address + amount, click "Send"
User enters:
To: 0x789...
Amount: 0.1 ETH
↓
React creates transaction object:
{
to: "0x789...",
value: "100000000000000000" (0.1 ETH in wei)
}
↓
ethers.js asks MetaMask to sign it
↓
MetaMask popup: "Send 0.1 ETH to 0x789...?"
Gas Fee: 0.0002 ETH
↓
User clicks "Confirm"
↓
MetaMask signs with your private key (securely, without exposing it)
↓
Transaction sent to blockchain
↓
Miners/validators include it in next block
↓
After ~15 seconds: ✅ Confirmed!
↓
React shows: "Transaction successful!"
Cost: ~21,000 gas (standard ETH transfer)
What you do: Type message, click "Post Message"
User types: "Hello blockchain!"
↓
React prepares contract call:
contract.setMessage("Hello blockchain!")
↓
ethers.js translates this to blockchain format (ABI encoding)
↓
MetaMask popup: "Interact with contract?"
Function: setMessage
Data: "Hello blockchain!"
Gas Fee: 0.0005 ETH (higher than ETH send)
↓
User approves
↓
Transaction sent to blockchain
↓
Blockchain runs your contract's setMessage() function
↓
Contract updates storage:
message = "Hello blockchain!"
lastWriter = 0x123... (your address)
lastUpdated = 1702857600
↓
Transaction confirmed!
↓
React shows: "Message posted!"
Cost: ~50,000 gas (writing data is expensive)
Why more expensive than sending ETH?
- Sending ETH: Simple transfer (minimal computation)
- Writing contract: Execute code + store data + emit event
What you do: App shows latest message automatically
React wants to read message
↓
ethers.js calls contract.getMessage()
↓
This is a "view" function (doesn't change anything)
↓
Blockchain returns: "Hello blockchain!"
↓
React displays the message
Cost: FREE (no transaction, just reading)
Think of gas like paying for compute time on a global computer:
Your Transaction
↓
Needs Processing
↓
┌─────────────────────────┐
│ Validator/Miner Says: │
│ "I'll process this if │
│ you pay me for:" │
│ │
│ 1. Electricity used │
│ 2. Storage forever │
│ 3. Network bandwidth │
└─────────────────────────┘
↓
You Pay Gas Fee
↓
Transaction Processed
Formula:
Total Cost = Gas Used × Gas Price
Example:
50,000 gas × 20 gwei/gas = 1,000,000 gwei = 0.001 ETH
Private Key (SECRET!)
"sk_9d7f8e6a5b4c3d2e1f"
│
│ Mathematical Magic
│ (One-way function)
↓
Public Address (SHARE THIS)
"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2"
Analogy:
- Private Key = Your house key (keep it secret!)
- Public Address = Your home address (anyone can send you mail)
If someone gets your private key = they own your crypto forever. No recovery possible.
┌──────────────────────┐
│ Your React Code │
│ │
│ const balance = │
│ await provider │
│ .getBalance(addr) │
└──────────┬───────────┘
│
│ Uses ethers.js
↓
┌──────────────────────┐
│ MetaMask │
│ (Provider/Signer) │
│ │
│ - Injects Web3 │
│ - Signs Txs │
└──────────┬───────────┘
│
│ JSON-RPC Protocol
│ (Standard Web3 API)
↓
┌──────────────────────┐
│ Ethereum Node │
│ (Infura/Alchemy │
│ or Local Node) │
│ │
│ - Blockchain Access │
│ - Sends Txs │
└──────────┬───────────┘
│
│ Peer-to-Peer Network
↓
┌──────────────────────┐
│ Ethereum Blockchain │
│ (Decentralized) │
│ │
│ - 1000s of Nodes │
│ - Global Consensus │
└──────────────────────┘
1. CREATED
└─> You prepare transaction in React
2. SIGNED
└─> MetaMask signs with private key
3. BROADCAST
└─> Sent to blockchain network (mempool)
Status: "Pending" ⏳
4. INCLUDED IN BLOCK
└─> Miner/validator picks it up
Still pending...
5. CONFIRMED (1 block)
└─> Added to blockchain
Status: "Success" ✅
(Or "Failed" ❌ if error)
6. FINALIZED (multiple confirmations)
└─> After 12+ blocks: Permanent
Cannot be reversed
A: NEVER store private keys in frontend code!
- Frontend JavaScript is visible to everyone
- Anyone could steal your key
- MetaMask keeps keys encrypted + protected
Sepolia Testnet:
✓ Fake ETH (free from faucets)
✓ Safe to experiment
✓ Same technology as mainnet
✓ Perfect for learning
✗ No real value
Ethereum Mainnet:
✓ Real ETH (costs money)
✓ Production environment
✗ Every mistake costs money
✗ Not for learning
A: Gas price fluctuates based on network demand:
Low Traffic: 10 gwei/gas → Cheap
Medium Traffic: 50 gwei/gas → Moderate
High Traffic: 200 gwei/gas → Expensive!
On Sepolia (testnet), fees are always low because fewer people use it.
A: NO! Contracts are immutable.
Deploy Contract
↓
Code Locked Forever
↓
Can't Change Logic
↓
(This is a feature, not a bug!)
Why? So users can trust the code won't change on them.
Solution: Deploy a new contract with fixes, but the old one stays forever.
This guide will be updated as we add more features!