Hedera
  • Welcome to Hedera — let’s build the future
  • Getting Started
    • Environment Setup
    • Web2 Developers
      • Transfer HBAR
      • Create a Token
      • Create a Topic
    • EVM Developers
      • Deploy a Contract
  • Tutorials
    • Smart Contracts
      • How to Mint & Burn an ERC-721 Token Using Hardhat and Ethers (Part 1)
      • How to Set Access Control, a Token URI, Pause, and Transfer an ERC-721 Token Using Hardhat (Part 2)
      • How to Upgrade an ERC-721 Token with OpenZeppelin UUPS Proxies and Hardhat (Part 3)
      • How to Verify a Smart Contract on HashScan
      • Deploy a Smart Contract Using Remix
      • Deploy a Smart Contract Using Hardhat and Hiero JSON-RPC Relay
      • Deploy Your First Smart Contract
      • Deploy a Contract Using the Hedera Token Service
      • Send and Receive HBAR Using Solidity Smart Contracts
      • Deploy By Leveraging Ethereum Developer Tools On Hedera
      • Deploy a Subgraph Using The Graph and Hedera JSON-RPC Relay
      • Deploy Smart Contracts on Hedera Using Truffle
      • The Power of Native Hedera Tokens as ERC-20 Tokens: A step-by-step guide
      • HTS x EVM - Part 1: How to Mint NFTs
      • HTS x EVM - Part 2: KYC & Update
      • HTS x EVM - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Hedera Smart Contracts Workshop
        • Setup
        • Solidity
        • Hedera SDK JS
        • Hardhat and EthersJs
        • Outro
      • Foundry
        • How to Setup Foundry and Write a Basic Unit Test
        • How to Deploy and Verify a Hedera Smart Contract with Foundry
        • How to Test A Solidity Event
        • How to Fork Testnet on Latest Block
    • Consensus
      • Submit Your First Message
      • Submit Message to Private Topic
      • Query Messages with Mirror Node
    • Tokens
      • Create and Transfer Your First NFT
      • Create and Transfer Your First Fungible Token
      • Create and Transfer an NFT using a Solidity Contract
      • Structure Your Token Metadata Using JSON Schema V2
      • Hedera Token Service - Part 1: How to Mint NFTs
      • Hedera Token Service - Part 2: KYC, Update, and Scheduled Transactions
      • Hedera Token Service - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Create Your First Frictionless Airdrop Campaign
    • Local Node
      • How to Run Hedera Local Node in a Cloud Development Environment (CDE)
        • Run a Local Node in Gitpod
        • Run a Local Node in Codespaces
      • How to Set Up a Hedera Local Node
      • Set Up a Hedera Local Node using the NPM CLI
    • More Tutorials
      • Create and Fund Your Hedera Testnet Account
      • How to Create a Personal Access Token (API Key) on the Hedera Portal
      • How to Auto-Create Hedera Accounts with HBAR and Token Transfers
      • How to Configure a Mirror Node and Query Data
      • How to Generate a Random Number on Hedera
      • Get Started with the Hedera Consensus Service Fabric Plugin
        • Virtual Environment Setup
      • Schedule Your First Transaction
      • How to Connect to Hedera Networks Over RPC
        • Configuring Hashio RPC endpoints
        • Configuring Hiero JSON-RPC Relay endpoints
        • Configuring Validation Cloud RPC endpoints
      • JavaScript Testing
      • Create a Hedera DApp Integrated with WalletConnect
      • How to Connect MetaMask to Hedera
    • Demo Applications
    • Starter Projects
    • Building on Hedera (course)
  • Networks
    • Mainnet
      • Mainnet Accounts
      • Mainnet Consensus Nodes
        • Node Deployment Requirements
          • FAQ
        • Node Deployment Process
      • Fees
        • Transaction Records
    • Testnets
      • Testnet Accounts
      • Testnet Consensus Nodes
    • Localnet
      • Single Node Configuration
      • Multinode Configuration
    • Network Explorers and Tools
    • Release Notes
      • Consensus Node
      • Hedera Mirror Node
  • Core Concepts
    • Accounts
      • Account Creation
      • Auto Account Creation
      • Account Properties
    • Keys and Signatures
    • Schedule Transaction
    • Smart Contracts
      • Understanding Hedera's EVM Differences and Compatibility
        • For EVM Developers Migrating to Hedera
          • Accounts, Signature Verification & Keys (ECDSA vs. ED25519)
          • JSON-RPC Relay and EVM Tooling
          • Token Management with Hedera Token Service
          • Decimal Handling (8 vs. 18 Decimals)
          • Handling HBAR Transfers in Contracts
        • For Hedera-Native Developers Adding Smart Contract Functionality
          • Integrating ED25519 Accounts and Advanced Features Into Smart Contracts
          • JSON-RPC Relay and State Queries
          • Extending Token Management with Smart Contracts
      • Creating Smart Contracts
      • Compiling Smart Contracts
      • System Smart Contracts
        • Hedera Account Service
        • Hedera Schedule Service
      • Gas and Fees
      • JSON-RPC Relay
      • Deploying Smart Contracts
      • Smart Contract Addresses
      • Verifying Smart Contracts
      • Smart Contract Traceability
      • Tokens Managed by Smart Contracts
        • ERC-20 (Fungible Tokens)
        • ERC-721 (Non-Fungible Token)
        • ERC-3643 Real World Assets (RWA)
        • ERC-1363 (Payable Tokens)
        • Hedera Token Service System Contract
      • Wrapped HBAR (WHBAR)
      • Smart Contract Rent
      • Smart Contract Security
      • EVM Archive Node Queries
    • Tokens
      • Tokenization on Hedera
      • Hedera Token Service (HTS) Native Tokenization
        • Token Types and ID Formats
        • Token Properties
        • Token Creation
        • Custom Fee Schedule
        • Token Airdrops
      • ERC/EVM-Compatible Tokenization
      • Hybrid (HTS + EVM ) Tokenization
    • Staking
      • Staking Program
      • Stake HBAR
    • Hashgraph Consensus Algorithm
      • Gossip About Gossip
      • Virtual Voting
    • Transactions and Queries
      • Transaction Properties
    • State and History
    • Mirror Nodes
      • Hedera Mirror Node
      • One Click Mirror Node Deployment
      • Run Your Own Mirror Node
        • Run Your Own Mirror Node with Google Cloud Storage (GCS)
        • Run Your Mirror Node with Amazon Web Services S3 (AWS)
  • Open Source Solutions and Integrations
    • AI Studio on Hedera
      • ElizaOS Plugin for Hedera
      • Hedera AI Agent Kit
      • MCP Server
      • OpenConvAI
    • AI Tools for Developers
      • Hedera Hivemind
      • Kapa AI
    • Asset Tokenization Studio (ATS)
      • Web User Interface (UI)
      • Frequently Asked Questions (FAQs)
    • HashioDAO
      • Governance Token DAO
      • NFT DAO
      • Multisig DAO
      • DAO Proposals
      • Local Environment Setup
    • Hedera CLI
    • Hedera Contract Builder
    • Hedera Custodians Library
      • How to use it
    • Hedera Developers Code Repository
    • Hedera Developer Playground
    • Hedera Wallet Snap By MetaMask
      • Hedera Wallet Snap Documentation
      • Tutorial: MetaMask Snaps – What Are They and How to Use Them
    • Interoperability and Bridging
      • LayerZero
    • NFT Studio
      • Airdrop List Verifier
      • Metadata Validator
      • NFT Rarity Inspector
      • NFT Token Holders List Builder
      • NFT Risk Calculator
      • Token Balance Snapshot
      • Hedera NFT SDK
    • Oracle Networks
      • Chainlink Oracles
      • Pyth Oracles
      • Supra Oracles
    • Stablecoin Studio
      • Core Concepts
      • Web UI Application
      • CLI Management
      • TypeScript SDK
    • Hedera Guardian
    • Hedera WalletConnect
  • SDKs & APIs
    • SDKs
      • Build Your Hedera Client
      • Set Up Your Local Network
      • Network Address Book
      • Keys
        • Generate a new key pair
        • Import an existing key
        • Create a key list
        • Create a threshold key
        • Generate a mnemonic phrase
        • Recover keys from a mnemonic phrase
      • HBAR
      • Specialized Types
      • Pseudorandom Number Generator
      • Transactions
        • Create a Batch Transaction
        • Transaction ID
        • Modify transaction fields
        • Create an unsigned transaction
        • Manually sign a transaction
        • Submit a transaction
        • Sign a multisignature transaction
        • Get a transaction receipt
        • Get a transaction record
      • Schedule Transaction
        • Schedule ID
        • Create a schedule transaction
        • Sign a scheduled transaction
        • Delete a schedule transaction
        • Get schedule info
        • Network Response Messages
      • Queries
      • General Network Response Messages
      • Accounts and HBAR
        • Create an account
        • Update an account
        • Transfer cryptocurrency
        • Approve an allowance
        • Delete an allowance
        • Delete an account
        • Get account balance
        • Get account info
        • Network Response Messages
      • Consensus Service
        • Create a topic
        • Update a topic
        • Submit a message
        • Delete a topic
        • Get topic messages
        • Get topic info
        • Network Response
      • Token Service
        • Token ID
        • NFT ID
        • Token types
        • Create a token
        • Custom token fees
        • Update a token
        • Update token custom fees
        • Update NFT metadata
        • Transfer tokens
        • Airdrop a token
        • Claim a token
        • Cancel a token
        • Reject a token
        • Delete a token
        • Mint a token
        • Burn a token
        • Freeze an account
        • Unfreeze an account
        • Enable KYC account flag
        • Disable KYC account flag
        • Associate tokens to an account
        • Dissociate tokens from an account
        • Pause a token
        • Unpause a token
        • Wipe a token
        • Atomic swaps
        • Get account token balance
        • Get token info
        • Get NFT info
        • Network Response Messages
      • File Service
        • Create a file
        • Append to a file
        • Update a file
        • Delete a file
        • Get file contents
        • Get file info
        • Network Response Messages
      • Smart Contract Service
        • Delegate Contract ID
        • Create a smart contract
        • Update a smart contract
        • Delete a smart contract
        • Call a smart contract function
        • Ethereum transaction
        • Get a smart contract function
        • Get smart contract bytecode
        • Get smart contract info
        • Hedera Service Solidity Libraries
        • Network Response Messages
      • Signature Provider
        • Provider
        • Signer
        • Wallet
        • Local Provider
    • Mirror Node REST API
      • Accounts
      • Balances
      • Blocks
      • Schedule Transactions
      • Smart Contracts
      • Tokens
      • Topics
      • Transactions
      • Network
    • Hedera Consensus Service gRPC API
    • Hedera APIs
      • Basic Types
        • AccountAmount
        • AccountID
        • ContractID
        • CryptoAllowance
        • CurrentAndNextFeeSchedule
        • FeeComponents
        • FeeData
        • FeeSchedule
        • FileID
        • Fraction
        • HederaFunctionality
        • Key
        • KeyList
        • NftAllowance
        • NftTransfer
        • NodeAddress
        • NodeAddressBook
        • RealmID
        • ScheduleID
        • SemanticVersion
        • ServicesConfigurationList
        • ServiceEndpoint
        • Setting
        • ShardID
        • Signature
        • SignatureList
        • SignatureMap
        • SignaturePair
        • SubType
        • TransferList
        • TransactionID
        • ThresholdKey
        • ThresholdSignature
        • TokenAllowance
        • TokenBalance
        • TokenBalances
        • TokenFreezeStatus
        • TokenPauseStatus
        • TokenID
        • TokenKycStatus
        • TokenRelationship
        • TokenTransferList
        • TokenType
        • TokenSupplyType
        • TopicID
        • TransactionFeeSchedule
      • Cryptocurrency Accounts
        • CryptoService
        • CryptApproveAllowance
        • CryptoDeleteAllowance
        • CryptoCreate
        • CryptoTransfer
        • CryptoUpdate
        • CryptoDelete
        • CryptoGetAccountBalance
        • CryptoGetAccountRecords
        • CryptoGetInfo
        • CryptoGetStakers
      • Consensus Service
        • Consensus Service
        • ConsensusCreateTopic
        • ConsensusUpdateTopic
        • ConsensusSubmitMessage
        • ConsensusDeleteTopic
        • ConsensusTopicInfo
        • ConsensusGetTopicInfo
      • Schedule Service
        • ScheduleService
        • SchedulableTransactionBody
        • ScheduleCreate
        • ScheduleDelete
        • ScheduleSign
        • ScheduleGetInfo
      • Token Service
        • TokenService
        • CustomFees
          • AssessedCustomFee
          • CustomFee
          • FractionalFee
          • FixedFee
          • RoyaltyFee
        • TokenCreate
        • TokenUpdate
        • TokenFeeScheduleUpdate
        • TokenDelete
        • TokenMint
        • TokenBurn
        • TokenFreezeAccount
        • TokenUnfreezeAccount
        • TokenGrantKyc
        • TokenRevokeKyc
        • TokenAssociate
        • TokenDissociate
        • TokenWipeAccount
        • TokenPause
        • TokenUnpause
        • TokenGetInfo
        • TokenGetNftInfo
        • TokenGetNftInfos
        • TokenGetAccountNftInfo
      • File Service
        • FileService
        • FileCreate
        • FileAppend
        • FileUpdate
        • FileDelete
        • FileGetContents
        • FileGetInfo
      • Smart Contracts
        • SmartContractService
        • ContractCall
        • ContractCallLocal
        • ContractCreate
        • ContractUpdate
        • ContractDelete
        • ContractGetByteCode
        • ContractGetInfo
        • ContractGetRecords
      • Miscellaneous
        • Duration
        • ExchangeRate
        • Freeze
        • FreezeType
        • GetByKey
        • GetBySolidityID
        • NetworkGetVersionInfo
        • NetworkService
        • Query
        • QueryHeader
        • Response
        • ResponseCode
        • ResponseHeader
        • SystemDelete
        • SystemUndelete
        • TimeStamp
        • Transaction
        • TransactionBody
        • TransactionContents
        • TransactionGetFastRecord
        • TransactionGetReceipt
        • TransactionGetRecord
        • TransactionReceipt
        • TransactionRecord
        • TransactionResponse
        • UncheckedSubmit
    • Hedera Status API
  • Support & Community
    • Glossary
    • Contributing to Hedera documentation
      • Contribution Guidelines
        • Creating Issues
        • Creating Pull Requests
        • Hedera Improvement Proposal (HIP)
        • Submit Demo Applications
      • Style Guide
        • Understanding different types of documentation
        • Use of HBAR and tinybars
        • Use of web2 and web3
        • Language and grammar
        • Formatting
        • Punctuation
        • GitBook Markdown Syntax
    • Discord
    • GitHub
    • Stack Overflow
    • Hedera Blog
    • Bug Bounty
    • Hedera Help
    • Documentation Survey
    • Meetups
    • Brand Guidelines
    • Status Page
Powered by GitBook
LogoLogo

INTRODUCTION

  • Fees
  • Core Concepts
  • Network Information

TOOLS

  • Bridge
  • Oracles
  • Explorers
  • Developer Portal & Faucet

RESOURCES

  • Status
  • Bug Bounty
  • Build on Hedera (course)
  • Documentation Survey
On this page
  • Prerequisites
  • Table of Contents
  • Step 1: Set Up Project
  • Step 2: Configure Project
  • Environment Variables
  • Hardhat Configuration File
  • Step 3: Compile Contract
  • Step 4: Test and Deploy Contract
  • Next Steps
  • Additional Resources

Was this helpful?

Edit on GitHub
  1. Tutorials
  2. Smart Contracts

Deploy a Smart Contract Using Hardhat and Hiero JSON-RPC Relay

A step-by-step guide on deploying a smart contract to Hedera testnet and Hiero Local Node using Hardhat.

PreviousDeploy a Smart Contract Using RemixNextDeploy Your First Smart Contract

Last updated 2 months ago

Was this helpful?

In this tutorial, you will walk through the step-by-step guide on deploying using Hardhat and Hiero JSON-RPC Relay. is a development environment for the EVM. It consists of different components for editing, compiling, debugging, and deploying smart contracts and dApps, all working together to create a complete development environment.

The is an implementation of Ethereum JSON-RPC APIs for Hedera and utilizes both Hiero Consensus Nodes and Mirror Nodes to support RPC queries defined in the . The project enables developers to establish their own local network for development and testing. The local network comprises the consensus node, mirror node, JSON-RPC relay, and other Hedera products, and can be set up using the CLI tool and Docker. This setup allows you to seamlessly build and deploy smart contracts from your local environment.

By the end of this tutorial, you'll be equipped to deploy smart contracts on the Hedera Testnet or your local Hedera node, leveraging Hardhat's tools for testing, compiling, and deploying.


Prerequisites

  • Basic understanding of smart contracts.

  • Basic understanding of and JavaScript.

  • Basic understanding of .


Table of Contents


Step 1: Set Up Project

Run the following command to clone the repo, change into the directory, and install dependencies:

git clone https://github.com/hashgraph/hedera-hardhat-example-project.git
cd hedera-hardhat-example-project
npm install

Open the project in Visual Studio Code or your IDE of choice. The project structure of the repo you just cloned should look like this:

hedera-hardhat-example-project
├── node_modules
├── contracts
├── scripts
├── test
├── .env.example
├── .gitignore
├── hardhat.config.js
├── package-lock.json
├── package.json
└── README.md
contracts/

The contracts/ folder contains the source file for the Greeter smart contract. Let's review the Greeter.sol contract in the hedera-example-hardhat-project/contracts folder. At the top of the file, the SPDX-License-Identifier defines the license, in this case, the MIT license. The pragma solidity ^0.8.9; line specifies the Solidity compiler version to use. These two lines are crucial for proper licensing and compatibility.

Greeter.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract Greeter {
    string private greeting;

    event GreetingSet(string greeting);

    //This constructor assigns the initial greeting and emit GreetingSet event
    constructor(string memory _greeting) {
        greeting = _greeting;

        emit GreetingSet(_greeting);
    }

    //This function returns the current value stored in the greeting variable
    function greet() public view returns (string memory) {
        return greeting;
    }

    //This function sets the new greeting msg from the one passed down as parameter and emit event
    function setGreeting(string memory _greeting) public {
        greeting = _greeting;

        emit GreetingSet(_greeting);
    }
}
scripts/

The scripts/ folder contains test scripts for locally testing a smart contract before deploying it. Please read the comments to help you understand the code and its purpose.

contractCall.js

Calls the setGreeting function from the Greeter contract and sets the greeter message to "Greeter."

contractCall.js
const { ethers } = require('hardhat');

//This function accepts two parameters - address and msg
//Retrieves the contract from the address and set new greeting
module.exports = async (address, msg) => {

  //Assign the first signer, which comes from the first privateKey from our configuration in hardhat.config.js, to a wallet variable. 
  const wallet = (await ethers.getSigners())[0];

  //Assign the greeter contract object in a variable, this is used for already deployed contract, which we have the address for. ethers.getContractAt accepts:
  //name of contract as first parameter
  //address of our contract
  //wallet/signer used for signing the contract calls/transactions with this contract 
  const greeter = await ethers.getContractAt('Greeter', address, wallet);

  //using the greeter object(which is our contract) we can call functions from the contract. In this case we call setGreeting with our new msg
  const updateTx = await greeter.setGreeting(msg);

  console.log(`Updated call result: ${msg}`);

  return updateTx;
};

contractViewCall.js

Returns the current greeter message value stored with the Greeter contract.

contractViewCall.js
const { ethers } = require("hardhat");

module.exports = async (address) => {
  //Assign the first signer, which comes from the first privateKey from our configuration in hardhat.config.js, to a wallet variable.
  const wallet = (await ethers.getSigners())[0];

  //Assign the greeter contract object in a variable, this is used for already deployed contract, which we have the address for. ethers.getContractAt accepts:
  //name of contract as first parameter
  //address of our contract
  //wallet/signer used for signing the contract calls/transactions with this contract
  const greeter = await hre.ethers.getContractAt("Greeter", address, wallet);
  //using the greeter object(which is our contract) we can call functions from the contract. In this case we call greet which returns our greeting msg
  const callRes = await greeter.greet();

  console.log(`Contract call result: ${callRes}`);

  return callRes;
};

deployContract.js

Deploys the Greeter contract and returns the contract public address.

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

module.exports = async () => {
  //Assign the first signer, which comes from the first privateKey from our configuration in hardhat.config.js, to a wallet variable.
  let wallet = (await ethers.getSigners())[0];

  //Initialize a contract factory object
  //name of contract as first parameter
  //wallet/signer used for signing the contract calls/transactions with this contract
  const Greeter = await ethers.getContractFactory("Greeter", wallet);
  //Using already intilized contract facotry object with our contract, we can invoke deploy function to deploy the contract.
  //Accepts constructor parameters from our contract
  const greeter = await Greeter.deploy("initial_msg");
  //We use wait to recieve the transaction (deployment) receipt, which contains contractAddress
  const contractAddress = (await greeter.deployTransaction.wait())
    .contractAddress;

  console.log(`Greeter deployed to: ${contractAddress}`);

  return contractAddress;
};

showBalance.js

Returns the balance of the specified wallet address (account) in tinybars. Tinybars are the unit in which Hedera accounts hold HBAR balances.

showBalance.js
const { ethers } = require("hardhat");

module.exports = async () => {
  //Assign the first signer, which comes from the first privateKey from our configuration in hardhat.config.js, to a wallet variable.
  const wallet = (await ethers.getSigners())[0];
  //Wallet object (which is essentially signer object) has some built in functionality like getBalance, getAddress and more
  const balance = (await wallet.getBalance()).toString();
  console.log(`The address ${wallet.address} has ${balance} weibars`);

  return balance;
};
test/
rpc.js
const hre = require("hardhat");
const { expect } = require("chai");

describe("RPC", function () {
  let contractAddress;
  let signers;

  before(async function () {
    signers = await hre.ethers.getSigners();
  });

  it("should be able to get the account balance", async function () {
    const balance = await hre.run("show-balance");
    expect(Number(balance)).to.be.greaterThan(0);
  });

  it("should be able to deploy a contract", async function () {
    contractAddress = await hre.run("deploy-contract");
    expect(contractAddress).to.not.be.null;
  });

  it("should be able to make a contract view call", async function () {
    const res = await hre.run("contract-view-call", { contractAddress });
    expect(res).to.be.equal("initial_msg");
  });

  it("should be able to make a contract call", async function () {
    const msg = "updated_msg";
    await hre.run("contract-call", { contractAddress, msg });
    const res = await hre.run("contract-view-call", { contractAddress });
    expect(res).to.be.equal(msg);
  });
});
.env.example
hardhat.config.js

Step 2: Configure Project

In this step, you will update and configure your environment variables and Hardhat configuration files. These files play a crucial role in defining tasks, securely storing account private keys, and specifying RPC endpoint URLs required for network interactions.

Environment Variables

The .env file securely stores environment variables, such as your Hedera network endpoints and private keys, which are then imported into the hardhat.config.js file. This helps protect sensitive information like your private keys and API secrets, but it's still best practice to add .env to .gitignore file to prevent you from committing and pushing your credentials to GitHub. Go to the tab corresponding to your deployment path and follow the steps to set up your environment variables.

  1. Rename the .env.example File Start by renaming the provided .env.example file to .env.

  2. Review the .env File Open the .env file to modify with your private keys and understand its contents.

Hiero Local Node environment variables

The variables are predefined for the purposes of this tutorial.

.env
# Your Hedera Local Node ECDSA account alias private key
LOCAL_NODE_OPERATOR_PRIVATE_KEY=0x105d050185ccb907fba04dd92d8de9e32c18305e097ab41dadda21489a211524
# Your Hedera Local Node JSON-RPC endpoint URL
LOCAL_NODE_ENDPOINT='http://localhost:7546/'

Variables explained

  • LOCAL_NODE_OPERATOR_PRIVATE_KEY: This is your Alias ECDSA hex-encoded private key for your Hedera Local Node. Replace the example value with your actual private key. Once you set up your local node and run the command to start, the accounts list for alias ECDSA private keys will be generated and returned to your console (see screenshot below). Replace the example value with your actual private key.

  • LOCAL_NODE_ENDPOINT: This is the URL endpoint for your Hedera Local Node's JSON-RPC Relay. Typically, this would be your localhost followed by the port number (http://localhost:7546/).

Hedera Testnet environment variables

.env
# Your testnet account ECDSA hex-encoded private key from the portal
TESTNET_OPERATOR_PRIVATE_KEY=0xb46751179bc8aa9e129d34463e46cd924055112eb30b31637b5081b56ad96129
# Your testnet JSON-RPC Relay endpoint URL
TESTNET_ENDPOINT='https://testnet.hashio.io/api'

Variables explained

  • TESTNET_OPERATOR_PRIVATE_KEY: This is your ECDSA hex-encoded private key for the Hedera Testnet. Replace the example value with your actual private key.

  • TESTNET_ENDPOINT: This is the URL endpoint for the Hedera Testnet's JSON-RPC Relay. Replace the example URL with the one you're using.

Configuring these environment variables enables your Hardhat project to interact with the Hedera network or your local node. Let's review the Hardhat configuration file, where these environment variables are loaded into.

Hardhat Configuration File

The Hardhat config (hardhat.config.js) file serves as the central configuration file for your Hardhat project. This file is crucial for specifying various settings, including Hardhat tasks, network configurations, compiler options, and testing settings. Let’s review the configuration settings.

Required Packages and Mocha Settings

These first lines import the required Hardhat plugins and the dotenv module that loads environment variables from the .env file. This will allow you to keep your private keys secure while using them in your dApp and will keep you from committing these to GitHub.

hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
require("@nomicfoundation/hardhat-chai-matchers");
require("@nomiclabs/hardhat-ethers");
require("dotenv").config(); // Import dotenv library to access the .env file

Hardhat Tasks

hardhat.config.js
//define hardhat task here, which can be accessed in our test file (test/rpc.js) by using hre.run('taskName')
task("show-balance", async () => {
  const showBalance = require("./scripts/showBalance");
  return showBalance();
});

task("deploy-contract", async () => {
  const deployContract = require("./scripts/deployContract");
  return deployContract();
});

task("contract-view-call", async (taskArgs) => {
  const contractViewCall = require("./scripts/contractViewCall");
  return contractViewCall(taskArgs.contractAddress);
});

task("contract-call", async (taskArgs) => {
  const contractCall = require("./scripts/contractCall");
  return contractCall(taskArgs.contractAddress, taskArgs.msg);
});

Solidity Compiler Settings

Here, the Solidity compiler version is set to "0.8.9". The optimizer is enabled with 500 runs to improve the contract's efficiency.

hardhat.config.js
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  mocha: {
    timeout: 3600000,
  },
  solidity: {
  version: "0.8.9",
  settings: {
    optimizer: {
      enabled: true,
      runs: 500,
    },
  },
},

Network Configurations

The networks object is essential for defining the Hedera networks your Hardhat project will connect to. Additionally, the defaultNetwork key specifies the network Hardhat will default to if none is specified at deployment.

.env
// Specifies which network configuration will be used by default when you run Hardhat commands. 
  defaultNetwork: "local",
  networks: {
    // Defines the configuration settings for connecting to Hedera local node
    local: {
      // Specifies URL endpoint for Hedera local node pulled from the .env file
      url: process.env.LOCAL_NODE_ENDPOINT,
      // Your local node operator private key pulled from the .env file
      accounts: [process.env.LOCAL_NODE_OPERATOR_PRIVATE_KEY],
    },
  },
.env
  // Specifies which network configuration will be used by default when you run Hardhat commands.
  defaultNetwork: "testnet",
  networks: {
    // Defines the configuration settings for connecting to Hedera testnet
    testnet: {
      // Specifies URL endpoint for Hedera testnet pulled from the .env file
      url: process.env.TESTNET_ENDPOINT,
      // Your ECDSA testnet account private key pulled from the .env file
      accounts: [process.env.TESTNET_OPERATOR_PRIVATE_KEY],
    },
  },

Key/value breakdown:

  • defaultNetwork: This property specifies which network configuration will be used by default when you run Hardhat commands.

  • networks: This property contains configurations for different networks you might connect to.

  • url: This specifies the URL endpoint for the network. The value is pulled from the .env file where the environment variables are defined.

  • accounts: This lists the private keys for the accounts you'll use when connecting to the network. The value is pulled from the .env file where the environment variables are defined.


Step 3: Compile Contract

Now that your project is configured compile your contract. Run the following command in the hedera-hardhat-example-project terminal:

npx hardhat compile
Console check ✅
Compiling...
Compiled 1 contract successfully

After the initial compilation, if you don't modify any files, nothing will be compiled when you run the compile command. To force a compilation you can use the --force flag or run npx hardhat clean to clear the cache and delete the artifacts to recompile.


Step 4: Test and Deploy Contract

Once your contract is compiled successfully, deploy the Greeter.sol smart contract. There are additional steps required if you're deploying to your local node:

🛠️ local node additional steps

Before you deploy your contract, let's ensure you have all the necessary tools open and running to avoid any issues.

  • Have two terminals open. One for each of these two project directories:

    • hedera-local-node

    • hedera-hardhat-example-project

  • Have Docker open and start your local node.

    • In the hedera-local-node terminal, start your local node by running hedera start -d.

Test

Test your contract before deploying it. In the hedera-hardhat-example-project terminal, run the following command to compile and test your contract:

npx hardhat test

Tests should pass with "4 passing" returned to the console. Otherwise, an error message will appear indicating the issue.

console check ✅
  RPC
The address 0xe261e26aECcE52b3788Fac9625896FFbc6bb4424 has 99999999999999991611392 weibars
    ✔ should be able to get the account balance (1127ms)
Greeter deployed to: 0xEc3D74D360a53Fe7104Be6aB4e25e27a90bF6aE4
    ✔ should be able to deploy a contract (11810ms)
Contract call result: initial_msg
    ✔ should be able to make a contract view call (265ms)
Updated call result: updated_msg
Contract call result: updated_msg
    ✔ should be able to make a contract call (4068ms)


  4 passing (34s)

Deploy

In the same terminal, run the following command to deploy your contract to the default network specified in your config file:

npx hardhat deploy-contract

Alternatively, you can target any network configured in your Hardhat config file. For testnet:

npx hardhat run --network testnet scripts/deployContract.js
console check ✅
Greeter deployed to: 0x157B93c04a294AbD88cF608672059814b3ea38aE

Next Steps

Stop Local Node

Deploy on Hedera Testnet

If you're up for it, follow the steps to deploy on the Hedera testnet and verify your contract.

View Contract on HashScan Network Explorer

The Network Explorer will return the information about the contract created and deployed to the Hedera Testnet. The "EVM Address" field is the public address of the contract that was returned to you in your terminal. The terminal returned the public address with the "0x" hex encoding appended to the public address. You will also notice a contract ID in 0.0.contractNumber (0.0.3478001) format. This is the contract ID used to reference the contract entity in the Hedera Network.

Verify Contract

Note: At the top of the explorer page, remember to switch the network to TESTNET before you search for the contract.


Additional Resources

To simplify the setup process, you can clone a boilerplate Hardhat example project from the hedera-hardhat-example-project . Open a terminal window and navigate to your preferred directory where your Hardhat project will be stored.

Let's review the Hardhat project folders/content. For more information regarding Hardhat projects, check out the . If you do not need to review the project contents, you can skip this optional step.

NOTE: The pragma solidity line must match the version of Solidity defined in the of your hardhat.config.js file.

The test/ folder contains the test files for the project. The rpc.js file is located in this folder in the hedera-example-hardhat-project project and references the Hardhat that are defined in the hardhat.config file. When the command npx hardhat test is run, the program executes the rpc.js file.

A file that stores your environment variables like your accounts, private keys, and references to Hedera network. Details of this file are available in of this tutorial.

The Hardhat configuration file. This file includes information about the Hedera network RPC URLs, accounts, and tasks defined. Details of this file are available in of this tutorial.

Prerequisite: A Hiero Local Node set up and running ().

Prerequisite: A Hedera testnet account from the .

For this tutorial, we'll use Hashio, an instance of the hosted by . You can use any JSON-RPC instance the community supports.

These lines define tasks that are accessed and executed from the or folders.

The compiled artifacts will be saved in the artifacts/ directory by default, or whatever your is. The metadata file generated in this directory will be used for the in a later step.

Note: If you have not set up your Hedera Local Node, you can do so by following tutorial and returning to this step once you complete the setup.

Stop your local node and remove Docker containers by running hedera stop or docker compose down in your hedera-local-node terminal. Reference the section of the local node setup tutorial.

You can view the contract you deployed by searching the smart contract public address in a supported . For this example, we will use the Network Explorer. Copy and paste your deployed Greeter.sol public contract address into the HashScan search bar.

Additionally, you can verify your contract using the HashScan verification feature (beta). Follow these to learn how.

Congratulations! 🎉 You have successfully learned how to deploy a smart contract using Hardhat and Hedera JSON-RPC Relay. Feel free to reach out in !

➡

➡

➡

➡

➡

smart contracts
Hardhat
Hiero JSON-RPC Relay
JSON-RPC Specification
Hiero Local Node
Node.js
Hardhat Ethereum Development Tool
Project Setup
Project Configuration
Environment Variables
Hardhat Config File
Compile Smart Contract
Deploy Smart Contract
Next Steps
Additional Resources
repository
Hardhat docs
module exports
tasks
Step 2
Step 2
setup tutorial
Hedera Developer Portal
Hedera JSON-RPC relay
Swirlds Labs
Configuring Hashio RPC endpoints
test/
scripts/
configured artifacts path
smart contract verification process
this
Stop Your Local Node
Hedera Network Explorer
HashScan
steps
Discord
Project Repository
Hiero Local Node Repository
Hiero JSON-RPC Relay Repository
Hiero Local Node Setup Tutorial
Hardhat Documentation

Writer: Krystal, Technical Writer

Editor: Simi, Sr. Software Manager

Editor: Nana, Sr Software Manager

Editor: Georgi, Sr Software Dev (LimeChain)

|

|

|

|

GitHub
Hashnode
GitHub
LinkedIn
GitHub
LinkedIn
GitHub
LinkedIn