Smart Contract Development

1. Dapp Architecture and Development Workflow

Decentralized applications (Dapps) differ from traditional centralized apps. They run on blockchains or distributed networks, and their logic and data are maintained collectively by multiple participants rather than a single entity.

Dapp development requires understanding:

  • Decentralized tech stack
  • Smart contract programming
  • Frontend & blockchain interaction

1.1 Dapp Architecture

Dapp architecture consists of four core components:

1. Frontend (User Interface)

  • Built with HTML, CSS, JavaScript (React, Vue, etc.)
  • Interacts with blockchain via wallet-injected provider or RPC node:
    • Read-only calls (e.g., eth_call) to fetch contract state, events, etc.
    • State-changing calls are signed by wallet and broadcast via RPC node
  • Integrates blockchain wallets (MetaMask) for authentication and transaction signing

2. Smart Contracts

  • Core logic of Dapp, deployed on blockchain
  • Executed automatically by blockchain rules
  • On Ethereum, written in Solidity and run on EVM

3. Indexer / Data Retriever

  • Captures events emitted by smart contracts (e.g., Transfer event for NFTs)
  • Stores processed data in traditional databases (PostgreSQL)
  • Enables frontend to query data efficiently
  • Example: retrieve all NFTs owned by an address by parsing Transfer events

4. Blockchain & Decentralized Storage

  • Blockchain stores smart contract state and transaction history
  • Decentralized storage (IPFS, Arweave) stores large unstructured data
  • Ensures data persistence and decentralization

1.2 Dapp Development Workflow

Workflow stages:

  1. Requirement Analysis & Planning

    • Define functionality: transfers, balance queries, voting, etc.
    • Select blockchain platform: Ethereum, Polygon, Solana, etc.
    • Design user experience (UX) for blockchain interactions
  2. Smart Contract Development

    • Write contracts in Solidity
    • Write unit tests to ensure correctness
    • Audit & optimize for security (reentrancy, integer overflow, etc.)
  3. Indexer Development

    • Determine what on-chain data frontend needs
    • Write indexer in TypeScript (frameworks: Ponder, Subgraph)
    • Deploy with Docker or use SaaS indexer services
  4. Frontend Development

    • Choose framework: React, Vue
    • Integrate wallets (MetaMask)
    • Fetch blockchain and indexer data for display
    • Handle transaction signing & submission
  5. Blockchain Interaction

    • Use Viem (recommended), Ethers.js, Wagmi
    • Read state: call contract functions
    • Send transactions: signed via wallet to execute contract functions
  6. Deployment & Launch

    • Deploy smart contracts: Hardhat or Foundry
      • Testnets: Sepolia, Holesky
      • Mainnet deployment
    • Frontend deployment: IPFS or traditional web hosting (Vercel)
    • Maintenance: updates, bug fixes, user feedback

1.3 Summary

Dapp development covers:

  • Requirement analysis
  • Smart contract programming
  • Indexer & frontend development
  • Deployment

Challenges unique to Dapps include:

  • User experience
  • Transaction handling
  • Security concerns
  • Blockchain transparency and immutability

2. Ethereum Development Environment Setup

2.1 Prerequisites

  • Node.js (managed with nvm)
  • npm or yarn
  • Git

Example commands:

1
2
3
4
5
6
7
8
9
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Install Node.js LTS
nvm install --lts
nvm use --lts

# Optional: install yarn
npm install -g yarn

2.2 Local Ethereum Development Chains

Option 1: Foundry (Rust-based, fast)

  • Install: curl -L https://foundry.paradigm.xyz | bash && foundryup
  • Tools:
    • forge: build, test, deploy, verify contracts
    • anvil: local dev node, Ethereum JSON-RPC compatible
    • cast: CLI for on-chain interactions
  • Example project initialization: forge init Counter
  • Compile: forge build
  • Test: forge test
  • Local node: anvil
  • Deployment:
1
2
export PRIVATE_KEY="your_private_key_here"
forge script script/Counter.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key $PRIVATE_KEY

Option 2: Hardhat (modern framework)

  • Install: npm install --global hardhat
  • Create project: npx hardhat
  • Start node: npx hardhat node
  • Deploy: npx hardhat run scripts/deploy.js --network localhost

2.3 Wallet and Frontend Integration

  • Use MetaMask as development wallet
  • Frontend libraries: Viem, Wagmi

2.4 Other Useful Tools

  • Remix IDE (browser-based)
  • OpenZeppelin contracts (npm install @openzeppelin/contracts)
  • Chainlink testnet integration for oracles

3. RPC Node Services

RPC (Remote Procedure Call) nodes bridge frontend apps and blockchain networks.

3.1 What is RPC?

  • RPC nodes run blockchain client software, maintaining a full node
  • Expose APIs for reading chain data, sending transactions, listening to events
  • Analogy: ATM machine connecting to bank

3.2 Role of RPC in Web3 Development

  • Read data: account balance, contract state, block info
  • Send transactions: broadcast signed tx, check confirmations, gas estimation
  • Event listening: subscribe to contract events via WebSocket
  • Network management: switch chains, query network info

3.3 JSON-RPC Protocol

  • Ethereum uses JSON-RPC 2.0
  • HTTP or WebSocket
  • Example request:
1
2
3
4
5
6
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0xAddress", "latest"],
"id": 1
}
  • Common methods:
    • eth_getBalance
    • eth_blockNumber
    • eth_sendTransaction
    • eth_call
    • eth_getTransactionReceipt
    • eth_getLogs

3.4 RPC Providers Comparison

Provider Features Free Tier Use Case
Alchemy Enterprise-grade, stable 300M requests/mo Production, enterprise apps
Infura Established, ConsenSys 100k requests/mo Dev/test, small projects
QuickNode High-performance, multi-chain Limited free tier High-frequency, real-time
Public Node Fully free, no registration Unlimited* Learning, personal projects
Ankr Multi-chain, decentralized Limited free tier Multi-chain dev

3.5 Getting and Using RPC Endpoints

  1. Register and create app (e.g., Alchemy)
  2. Get RPC URL (e.g., https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY)
  3. Use in code:

Viem Example

1
2
3
4
5
6
7
8
9
10
11
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = createPublicClient({
chain: mainnet,
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY')
})

const balance = await client.getBalance({
address: '0xAddress'
})

Ethers.js Example

1
2
3
const { ethers } = require('ethers')
const provider = new ethers.JsonRpcProvider('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY')
const balance = await provider.getBalance('0xAddress')

Web3.js Example

1
2
3
const { Web3 } = require('web3')
const web3 = new Web3('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY')
const balance = await web3.eth.getBalance('0xAddress')

3.6 Hardhat Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require('@nomicfoundation/hardhat-toolbox')

module.exports = {
solidity: '0.8.19',
networks: {
mainnet: {
url: process.env.MAINNET_RPC_URL || '',
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
sepolia: {
url: process.env.SEPOLIA_RPC_URL || '',
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
},
}
  • .env file:
1
2
3
MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY
PRIVATE_KEY=your_private_key_here

3.7 RPC Best Practices

  • Protect API Keys: use .env, ignore in Git
  • Error handling & retries: handle network failures
  • Rate limiting: throttle requests, use WebSocket for high-frequency
  • Multi-node redundancy: fallback to multiple RPCs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const rpcUrls = [
'https://eth-mainnet.g.alchemy.com/v2/KEY1',
'https://eth-mainnet.infura.io/v3/KEY2',
'https://rpc.ankr.com/eth'
]

async function callWithFallback(method, params) {
for (const url of rpcUrls) {
try {
const client = createPublicClient({ chain: mainnet, transport: http(url) })
return await client.request({ method, params })
} catch {
console.warn(`RPC ${url} failed, trying next...`)
}
}
throw new Error('All RPC endpoints failed')
}
  • Monitoring: log success rate, latency, and usage
  • Local nodes: use Hardhat Node or Anvil for dev/test