DEV Community

Abhishek Tripathi
Abhishek Tripathi

Posted on

Build Your First dApp on the Avalanche Fuji Network

A Beginner's Step-by-Step Guide

Who this is for: Complete beginners who want to build any decentralized application on the Avalanche Fuji testnet(C-Chain).


📋 Table of Contents

  1. Prerequisites
  2. Set Up Your Wallet (Core or MetaMask)
  3. Get Free Test AVAX from the Faucet
  4. Set Up Your Development Environment
  5. Write Your Smart Contract
  6. Deploy to Fuji
  7. Connect a Frontend
  8. Example dApps to Build
  9. Troubleshooting
  10. Next Steps

1. Prerequisites

Before you start, make sure you have the following installed:

Required Software

Tool Purpose Install
Node.js (v18+) Runs JavaScript tools nodejs.org
npm or yarn Package manager Comes with Node.js
Core or MetaMask Browser wallet core.app metamask.io
Git Version control git-scm.com
A code editor Writing code VS Code recommended

Helpful (but not required) Knowledge

  • Basic JavaScript
  • What a blockchain/wallet is
  • What a smart contract does (roughly)

💡 You do not need to know Solidity before starting — this guide will walk you through it.


2. Set Up Your Wallet (Core or MetaMask)

Step 1 – Install Core or MetaMask

  1. Go to core.app or metamask.io and install the browser extension.
  2. Create a new wallet and safely store your seed phrase (12 words). Never share it with anyone.

Step 2 – Add the Fuji Network to Core or MetaMask

MetaMask doesn't include Fuji by default. Add it manually:

  1. Open Metamask → click the network dropdown at the top → Add network
  2. Click Add a network manually
  3. Enter the following details exactly:
Field Value
Network Name Avalanche Fuji Testnet
New RPC URL https://api.avax-test.network/ext/bc/C/rpc
Chain ID 43113
Currency Symbol AVAX
Block Explorer URL https://testnet.snowtrace.io
  1. Click Save and switch to the Fuji network.

✅ You should now see "Avalanche Fuji Testnet" in your MetaMask network list.


3. Get Free Test AVAX from the Faucet

You need test AVAX to pay for gas (transaction fees) when deploying contracts.

Steps

  1. Go to the official faucet: https://build.avax.network/console/primary-network/faucet
  2. Select Fuji as the network and C-Chain as the chain.
  3. Paste in your Core or MetaMask wallet address.
  4. Click Request 0.5 AVAX.
  5. Check your Core or Metamask balance.

⚠️ The faucet may ask you to log in with a GitHub account to prevent abuse. This is normal.


4. Set Up Your Development Environment

We'll use Hardhat — the most beginner-friendly Ethereum/Avalanche development framework.

Step 1 – Create a project folder

mkdir my-fuji-dapp
cd my-fuji-dapp
npm init -y
Enter fullscreen mode Exit fullscreen mode

Step 2 – Install Hardhat and dependencies

npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox dotenv
Enter fullscreen mode Exit fullscreen mode

Step 3 – Initialize Hardhat

npx hardhat init
Enter fullscreen mode Exit fullscreen mode

When prompted:

  • Choose "Create a JavaScript project"
  • Accept all default options by pressing Enter

Your folder structure will look like this:

my-fuji-dapp/
├── contracts/        ← Your Solidity smart contracts go here
├── scripts/          ← Deployment scripts go here
├── test/             ← Tests go here
├── hardhat.config.js ← Main config file
└── package.json
Enter fullscreen mode Exit fullscreen mode

Step 4 – Configure Hardhat for Fuji

Create a .env file in your root folder:

touch .env
Enter fullscreen mode Exit fullscreen mode

Add your wallet's private key (find this in MetaMask → Account Details → Show Private Key):

# .env
PRIVATE_KEY=your_metamask_private_key_here
Enter fullscreen mode Exit fullscreen mode

🔐 IMPORTANT: Never commit your .env file to GitHub. Add it to .gitignore:

echo ".env" >> .gitignore

Now open hardhat.config.js and replace its contents with:

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.20",
  networks: {
    fuji: {
      url: "https://api.avax-test.network/ext/bc/C/rpc",
      chainId: 43113,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

5. Write Your Smart Contract

Smart contracts are written in Solidity. Here are two beginner-friendly examples.

Example A – Simple Voting Contract

Create the file contracts/Voting.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Voting {
    // Stores vote counts for each candidate
    mapping(string => uint256) public votes;

    // List of valid candidates
    string[] public candidates;

    // Tracks who has already voted
    mapping(address => bool) public hasVoted;

    constructor(string[] memory _candidates) {
        candidates = _candidates;
    }

    // Cast a vote
    function vote(string memory candidate) public {
        require(!hasVoted[msg.sender], "You have already voted!");
        require(isValidCandidate(candidate), "Invalid candidate");

        votes[candidate]++;
        hasVoted[msg.sender] = true;
    }

    // Get vote count for a candidate
    function getVotes(string memory candidate) public view returns (uint256) {
        return votes[candidate];
    }

    // Internal check: is this a valid candidate?
    function isValidCandidate(string memory name) internal view returns (bool) {
        for (uint i = 0; i < candidates.length; i++) {
            if (keccak256(bytes(candidates[i])) == keccak256(bytes(name))) {
                return true;
            }
        }
        return false;
    }
}
Enter fullscreen mode Exit fullscreen mode

Example B – Simple NFT Contract

Create the file contracts/MyNFT.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721, Ownable {
    uint256 public tokenCounter;

    constructor() ERC721("MyNFT", "MNFT") Ownable(msg.sender) {
        tokenCounter = 0;
    }

    // Mint a new NFT to an address
    function mintNFT(address recipient) public onlyOwner returns (uint256) {
        uint256 newTokenId = tokenCounter;
        _safeMint(recipient, newTokenId);
        tokenCounter++;
        return newTokenId;
    }
}
Enter fullscreen mode Exit fullscreen mode

For the NFT contract, first install OpenZeppelin:

npm install @openzeppelin/contracts

6. Deploy to Fuji

Step 1 – Compile your contract

npx hardhat compile
Enter fullscreen mode Exit fullscreen mode

You should see: Compiled X Solidity file(s) successfully

Step 2 – Write a deployment script

Create the file scripts/deploy.js:

const { ethers } = require("hardhat");

async function main() {
  const [deployer] = await ethers.getSigners();
  console.log("Deploying with account:", deployer.address);

  // For the Voting contract:
  const Voting = await ethers.getContractFactory("Voting");
  const voting = await Voting.deploy(["Alice", "Bob", "Charlie"]);
  await voting.waitForDeployment();

  console.log("✅ Voting contract deployed to:", await voting.getAddress());

  // Uncomment below to deploy the NFT instead:
  // const MyNFT = await ethers.getContractFactory("MyNFT");
  // const nft = await MyNFT.deploy();
  // await nft.waitForDeployment();
  // console.log("✅ NFT contract deployed to:", await nft.getAddress());
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
Enter fullscreen mode Exit fullscreen mode

Step 3 – Deploy to Fuji

npx hardhat run scripts/deploy.js --network fuji
Enter fullscreen mode Exit fullscreen mode

You'll see output like:

Deploying with account: 0xYourWalletAddress
✅ Voting contract deployed to: 0xYourContractAddress
Enter fullscreen mode Exit fullscreen mode

Copy and save that contract address! You'll need it to interact with your contract.

Step 4 – Verify on the Block Explorer

  1. Go to testnet.snowtrace.io
  2. Search for your contract address
  3. You should see your deployment transaction 🎉

7. Connect a Frontend

Once your contract is deployed, you can build a simple web UI to interact with it.

Tools you'll use

  • ethers.js — JavaScript library to talk to the blockchain
  • HTML/React — For the user interface

Minimal HTML Example

Create frontend/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>My Fuji dApp</title>
  <script src="https://cdn.ethers.io/lib/ethers-5.7.umd.min.js"></script>
</head>
<body>
  <h1>🗳️ Vote on Fuji</h1>
  <button onclick="connectWallet()">Connect MetaMask</button>
  <br/><br/>
  <input id="candidate" placeholder="Enter candidate name" />
  <button onclick="castVote()">Vote</button>
  <p id="status"></p>

  <script>
    const CONTRACT_ADDRESS = "0xYourDeployedContractAddress";
    const ABI = [
      "function vote(string memory candidate) public",
      "function getVotes(string memory candidate) public view returns (uint256)"
    ];

    let signer;

    async function connectWallet() {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      await provider.send("eth_requestAccounts", []);
      signer = provider.getSigner();
      document.getElementById("status").innerText = "✅ Wallet connected!";
    }

    async function castVote() {
      const candidate = document.getElementById("candidate").value;
      const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
      const tx = await contract.vote(candidate);
      await tx.wait();
      document.getElementById("status").innerText = `✅ Voted for ${candidate}!`;
    }
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Replace 0xYourDeployedContractAddress with the address from Step 7.


8. Example dApps to Build

Once you've got the basics down, here are ideas for full projects on Fuji:

dApp What it does Key Solidity Concepts
Voting System Users vote on proposals, results are on-chain mapping, require, events
NFT Marketplace Mint, buy, sell NFTs ERC721, payable, transfer
Crowdfunding Users pledge AVAX to a goal payable, refund logic
Token Launch Create your own ERC20 token ERC20 standard, decimals
Simple DAO Members vote on treasury proposals access control, quorum logic

9. Troubleshooting

❌ "Transaction failed" on deployment

  • Check your MetaMask is set to Fuji, not mainnet
  • Make sure you have enough test AVAX (you need at least 0.1 AVAX)

❌ "Invalid private key" error

  • Make sure there's no extra space in your .env file
  • The key should start with 0x or be the raw 64-character hex string

❌ "Cannot find module" errors

  • Run npm install again to make sure all packages are installed

❌ MetaMask not detecting Fuji

  • Double-check the Chain ID is 43113 (not 43114)
  • Try removing and re-adding the network in MetaMask

❌ Faucet says "already requested"

  • The faucet has a cooldown period (usually 24 hours per address)
  • Create a second MetaMask wallet address to get more test AVAX

10. Next Steps

You've deployed your first dApp on Fuji! Here's how to keep growing:

  1. Verify your contract on Snowtrace so others can read the source code
  2. Write tests using Hardhat (npx hardhat test) to catch bugs early
  3. Learn more Solidity at solidity-by-example.org
  4. Explore OpenZeppelin contracts for secure, reusable building blocks
  5. Move to mainnet once you're confident — just change the network in hardhat.config.js

Useful Links

Resource URL
Avalanche Builder Hub https://build.avax.network/
Fuji Faucet https://build.avax.network/console/primary-network/faucet
Fuji Block Explorer testnet.snowtrace.io
Hardhat Docs hardhat.org
OpenZeppelin Contracts openzeppelin.com/contracts
Solidity Docs docs.soliditylang.org

🏔️ Happy building on Fuji! The testnet is your sandbox — experiment freely, break things, and learn fast before going to mainnet.

Top comments (0)