Deploy Contract With Hardhat

Hardhat is one of the popular smart contract development frameworks. It consists of different components for editing, compiling, debugging and deploying your smart contracts and dApps, all of which work together to create a complete development environment.

Hardhat smart contract

  • mkdir <project-name>;cd <project-name>

  • Initialize a project with Hardhat: npx hardhat init.

$ npx hardhat init
888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

👷 Welcome to Hardhat v2.22.6 👷‍

? What do you want to do? …
❯ Create a JavaScript project
  Create a TypeScript project
  Create a TypeScript project (with Viem)
  Create an empty hardhat.config.js
  Quit
  • Choose Create a TypeScript project.

  • Press <ENTER> to set the project root.

  • Press <ENTER> again to accept the addition of .gitignore.

  • Type y to accept installing sample project's dependencies.

  • Open the hardhat.config.ts file and paste the below code:

import "@nomicfoundation/hardhat-toolbox";
import "dotenv/config";
import { HardhatUserConfig } from "hardhat/config";
import "./tasks/deploySC";

const privateKey = process.env.PRIVATE_KEY;
if (!privateKey) {
  throw new Error("private key not found");
}

const config: HardhatUserConfig = {
  solidity: "0.8.24",
  networks: {
    biteigenTestnet: {
      url: "https://rpc-testnet.biteigen.xyz",
      chainId: 1022,
      accounts: [`0x${privateKey}`]
    },
  },
  etherscan: {
    apiKey: {
      biteigenTestnet: "apikey",
    },
    customChains: [
      {
        network: "biteigenTestnet",
        chainId: 1022,
        urls: {
          apiURL: "https://explorer-testnet.biteigen.xyz/api",
          browserURL: "https://explorer-testnet.biteigen.xyz/",
        }
      }
    ],
  },
};

export default config;

Add deploy task

  • Create a new file, in the contracts folder, named Counter.sol: touch contracts/Counter.sol.

  • Copy the below code and paste it in the Counter contract code:

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

contract Counter {
uint256 currentCount = 0;

    function increment() public {
        currentCount = currentCount + 1;
    }

    function retrieve() public view returns (uint256){
        return currentCount;
    }
}
  • Create a new file in the tasks folder deploySC.ts: touch tasks/deploySC.ts.

  • Add the code below to the deploySC.ts file:

import { task } from "hardhat/config";
import { HardhatRuntimeEnvironment } from "hardhat/types";

/**
  * usage: npx hardhat deploySC --network biteigenTestnet
  */

async function deploySC(_taskArgs: {}, hre: HardhatRuntimeEnvironment) {
  const factory = await hre.ethers.getContractFactory("Counter")
  const tx = await factory.deploy();
  await tx.waitForDeployment();
  console.log(
    `Counter contract deployed to https://https://explorer-testnet.biteigen.xyz/address/${tx.target}`
  );
}

task('deploySC', 'deploy Counter contract')
  .setAction(deploySC);
  • Now run the task:

npx hardhat deploySC --network biteigenTestnet

​Here’s an output example:

Counter contract deployed to 
https://https://explorer-testnet.biteigen.xyz/address/0xCF79A6a817F49cE37e7AE73F49A1A5a90FC28c84

Update frontend

The next step is to turn Counter.sol into a dApp by importing the ethers and the Counter file, as well as logging the contract’s ABI.

  • Include the below code in the App.ts file:

import { ethers } from "ethers";
import { useEffect, useState } from 'react';
import './App.css';

const counterAddress = "0xCF79A6a817F49cE37e7AE73F49A1A5a90FC28c84"
const abi = `[{"inputs":[],"name":"increment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`;

function App() {
  const [isLoading, setIsLoading] = useState(false);
  const [count, setCount] = useState(0);
  useEffect(() => {
    const fetchCount = async () => {
      const data = await readCounterValue();
      return data;
    };

    fetchCount().catch(console.error);
  }, []);

  async function requestAccount() {
    await window.ethereum?.request?.({ method: "eth_requestAccounts" });
  }

  async function updateCounter() {
    if (typeof window.ethereum === "undefined") return;
    await requestAccount();
    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(counterAddress, abi, signer);
    const transaction = await contract.increment();
    setIsLoading(true);
    await transaction.wait();
    setIsLoading(false);
    readCounterValue();
  }

  async function readCounterValue() {
    if (typeof window.ethereum === "undefined") return;
    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const contract = new ethers.Contract(
      counterAddress,
      abi,
      provider
    );

    try {
      const data = await contract.retrieve();
      setCount(parseInt(data.toString()));
    } catch (err) {
      alert(
        "Switch your MetaMask network to BitEigen Testnet and refresh this page!"
      );
    }
  }
  const incrementCounter = async () => {
    await updateCounter();
  };

  return (
    <div className="container">
      <button
        onClick={incrementCounter}
        disabled={isLoading}
        className="button"
      >
        {isLoading ? "loading..." : `counter: ${count}`}
      </button>
    </div>
  );
}

export default App;
  • Update the counterAddress to your deployed address.

It is the hexadecimal number found at the tail-end of the output of the last npx hardhat deploySC ... command and looks like this 0xCF79A6a817F49cE37e7AE73F49A1A5a90FC28c84.

Now, run the Counter dApp by simply using npm run start in CLI at the project root.

You have successfully deployed a dApp on the BitEigen Testnet.

Full Source Code

You can find the full source code on GitHub: Full Source Code on GitHub.

Last updated