Smart Contract Frontend — FundMe dApp

A lightweight vanilla JavaScript frontend that connects the MetaMask wallet to a FundMe smart contract deployed on a local Hardhat node. Built to learn the Web3 frontend stack end-to-end: wallet integration, contract interaction, and transaction confirmation handling — with no build tools, no framework, no npm deps.

Ethers.js MetaMask Hardhat Language


What this project does

This is the frontend half of a Fund Me / Crowdfunding dApp. Users connect their MetaMask wallet, fund a smart contract with ETH, check the contract balance, and the owner withdraws the collected funds. The contract enforces a minimum USD contribution (via a Chainlink price feed) through the FundMe.sol contract.

Button Action
Connect Requests MetaMask accounts (eth_requestAccounts)
Fund Sends ETH to the contract's fund() function
getBalance Reads the contract's ETH balance
Withdraw Owner calls withdraw() to pull collected funds

The index.html page has zero build step — just open it and the ES-module scripts load the bundled ethers.js from ./ethers-5.6.esm.min.js.

What I learned building this

This project was my hands-on introduction to building decentralized app frontends. Key concepts I worked through:

  • Connecting a wallet — using window.ethereum and eth_requestAccounts to let MetaMask handle accounts / signing / gas.
  • Provider, Signer & Contract — the core ethers.js objects:
    • Web3Provider = connection to the blockchain
    • Signer = the wallet that pays gas
    • Contract = the on-chain program you call
  • ABI & contract address — feeding the compiled FundMe.json ABI and the deployed address (from artifacts/contracts/FundMe.sol/FundMe.json) into ethers.
  • Sending transactionsfund() with { value: parseEther(amount) }.
  • Reading stategetBalance() with formatEther.
  • Transaction confirmation — listening via provider.once(hash, cb) instead of just wait(), so the UI knows when a tx is mined.
  • MetaMask quirk handling — resetting the account when a localhost Hardhat node restarts and the nonce resets to 0.
  • ES modules over CDN-free bundles — both ethers-5.6 (used here) and ethers-6.13.2 are included for experimentation.

Companion repo: the Solidity / Hardhat backend for this contract (FundMe.sol, Chainlink price feed, deploy scripts) lives in my Hardhat learning repo.

Getting started

Requires a local Hardhat node running the FundMe contract, and the MetaMask extension in Google Chrome.

1. Run the local node

yarn hardhat node      # prints private keys for test accounts
yarn hardhat deploy    # prints the FundMe contract address

2. Point the frontend at your contract

Update the address + ABI in constants.js:

export const contractAddress = "0x...";   // from hardhat deploy
export const abi = [ /* from artifacts/contracts/FundMe.sol/FundMe.json (abi only) */ ];

3. Set up MetaMask

  1. Add the localhost network
    • Settings → Networks → Add a network
    • RPC URL: http://127.0.0.1:8545/
    • Chain ID: 31337 (default Hardhat chain)
    • Currency symbol: ETH
  2. Import a test account via the private key printed by yarn hardhat node.
  3. Open index.html and click Connect, then Fund.

Troubleshooting

  • MetaMask prompt / nonce errorsReset account in MetaMask. When the localhost node restarts, the nonce resets to 0, so MetaMask must forget the old one too.
  • Buttons show "Please install MetaMask" → MetaMask isn't injected into this tab.

Project structure

├── index.html          # UI (vanilla HTML + buttons)
├── index.js            # wallet connect, fund, withdraw, balance logic (ES module)
├── constants.js        # deployed contract address + ABI
├── ethers-5.6.esm.min.js   # bundled ethers.js v5 (ESM)
├── ethers-6.13.2.min.js    # bundled ethers.js v6 (for comparison / upgrades)
├── package.json        # prettier only — no runtime deps
└── yarn.lock

Tech stack

  • ethers.js 5.6 — Web3Provider / Signer / Contract / utils
  • MetaMask — browser wallet provider (window.ethereum)
  • Hardhat — local blockchain for testing (companion repo)
  • Vanilla JS ES modules — no build step, no framework

About me / Open to work

I'm Hoelee, a hands-on developer transitioning from traditional Web2 development (PHP / CodeIgniter, Java / Spring, WordPress, JS) into Web3 / blockchain development. I'm working through the full stack — Solidity, ERC-20 / ERC-721, upgradeable contracts, OpenZeppelin, Hardhat & Foundry, Chainlink oracles, ethers.js / web3.js — and building real projects like this one to prove it.

This is a learning repository, so the code is intentionally simple, readable, and well-commented rather than production-hardened — it reflects what I learned while building it.

I'm open to remote opportunities in blockchain / full-stack web development. Let's talk:


Built while following the Smart Contract Engineer learning path. Frontend for the FundMe contract — send ETH to support a project, and the owner withdraws when ready.

Description
Learning project: vanilla JS + ethers.js dApp frontend for the FundMe smart contract - MetaMask wallet, fund/withdraw/balance, Chainlink price feed, local Hardhat node.
Readme 415 KiB
Languages
JavaScript 92%
HTML 8%