Deploy with Hardhat
Hardhat is one of the popular smart contract development frameworks.
This document is a guide on how to deploy a smart contract on the Conla network using Hardhat.
Hardhat smart contract
mkdir <project-name>;cd <project-name>
Initialize a project with Hardhat:
npx hardhat
.Next, (… To avoid failure … please go slow with this cli dialogue…),
So then,
Press
<ENTER>
to set the project root.Press
<ENTER>
again to accept addition of.gitignore
.Type
n
to reject installingsample project's dependencies
.The idea here is to postpone installing dependencies to later steps due to a possible version-related bug.
Open the
hardhat.config.js
file and paste the below code:Copy
require("dotenv").config(); require("@nomicfoundation/hardhat-toolbox"); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.9", paths: { artifacts: "./src", }, networks: { conla-testnet: { url: `https://testnet-rpc.conla.com`, accounts: [process.env.ACCOUNT_PRIVATE_KEY], }, }, };
Note that a different path to artifacts is added so that the React app will be able to read the contract ABI within the
src
folder.
Add scripts
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:
Copy
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; 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 scripts folder
deploy-counter.js
:touch scripts/deploy-counter.js
.Add the code below to the
deploy-counter.js
file:Copy
const hre = require("hardhat"); async function main() { const deployedContract = await hre.ethers.deployContract("Counter"); await deployedContract.waitForDeployment(); console.log( `Counter contract deployed to https://explorer.conla.com/address/${deployedContract.target}` ); } main().catch((error) => { console.error(error); process.exitCode = 1; });
Before compiling the contract, you need to install the toolbox. You may need to change directory to install outside the project. Use this command:
Copy
npm install --save-dev @nomicfoundation/hardhat-toolbox
Compile your contract code (i.e., go back to the project root in the CLI):
Copy
npx hardhat compile
Now run the scripts:
Copy
npx hardhat run scripts/deploy-counter.js --network conla-testnet
Here’s an output example:
Counter contract deployed to https://explorer.conla.com/address/0x5FbDB2315678afecb367f032d93F642f64180aa3
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.js
file:Copy
import { ethers } from "ethers"; import Counter from "./contracts/Counter.sol/Counter.json"; const counterAddress = "your-contract-address" console.log(counterAddress, "Counter ABI: ", Counter.abi);
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 run ...
command and looks like this0x5FbDB2315678afecb367f032d93F642f64180aa3
.It must be pasted in the
App.js
to replaceyour-contract-address
. Be sure to use the deployed address from your own implementation!
Update frontend counter to read from blockchain. Include the below code in the
App.js
file:Copy
useEffect(() => { // declare the data fetching function const fetchCount = async () => { const data = await readCounterValue(); return data; }; fetchCount().catch(console.error); }, []); async function readCounterValue() { if (typeof window.ethereum !== "undefined") { const provider = new ethers.providers.Web3Provider(window.ethereum); console.log("provider", provider); const contract = new ethers.Contract( counterAddress, Counter.abi, provider ); console.log("contract", contract); try { const data = await contract.retrieve(); console.log(data); console.log("data: ", parseInt(data.toString())); setCount(parseInt(data.toString())); } catch (err) { console.log("Error: ", err); alert( "Switch your MetaMask network to Conla Testnet and refresh this page!" ); } } }
Also, to import
useEffect
, insert it like this:Copy
import { useState, useEffect } from "react";
To be able to track a loader, add this to your state:
Copy
const [isLoading, setIsLoading] = useState(false);
This is within the
App()
function.
Let frontend counter write to the blockchain by adding the below
requestAccount
andupdateCounter
functions:Copy
async function requestAccount() { await window.ethereum.request({ method: "eth_requestAccounts" }); } async function updateCounter() { if (typeof window.ethereum !== "undefined") { await requestAccount(); const provider = new ethers.providers.Web3Provider(window.ethereum); console.log({ provider }); const signer = provider.getSigner(); const contract = new ethers.Contract(counterAddress, Counter.abi, signer); const transaction = await contract.increment(); setIsLoading(true); await transaction.wait(); setIsLoading(false); readCounterValue(); } }
Place these two functions above the
readCounterValue()
function in theApp.js
file.Replace the
incrementCounter
function with this one:Copy
const incrementCounter = async () => { await updateCounter(); };
Update the increment button code to:
Copy
<Button onClick={incrementCounter} variant="outlined" disabled={isLoading} > {isLoading ? "loading..." : "+1"} </Button>
Now, run the Counter dApp by simply using npm start
in CLI at the project root.
You have successfully deployed a dApp on the Conla testnet.