Deploy a Simple Smart Contract


This article shows how to deploy a simple smart contract using Hardhat on any of Quai Network's 9 chains.
Note: this tutorial covers deploying a simple, non SolidityX based smart contract to a single chain within Quai Network. For more complex deployments involving SolidityX or multi-chain deployments, visit the Advanced Tutorial Page.



To use Hardhat, you'll need the LTS version of nodejs. NodeJS bundles npm and npx.
Hardhat also supports yarn usage.


Hardhat is an EVM development environment for professionals written in TypeScript. It is useful for performing frequent tasks such as running tests, automatically checking code for mistakes, or interacting with a smart contract.

Quai Network and Solidity

It is useful to have basic knowledge of both Quai Network and Solidity. Quai Network utilizes a modified version of Solidity named SolidityX that provides support for additional opcodes.
Deployment of a smart contract on a Quai Network chain requires:
  • An active instance of a Quai Network full node or a remote node's RPC endpoint.
  • Sufficient balance in the address that you are deploying with.

Environment Setup

Initialize Hardhat

Hardhat is utilized through a local installation within individual project directories. Start by creating an npm project.
We'll be installing a slightly modified version of Hardhat called quai-hardhat. Quai-hardhat adds SolidityX compiler support while retaining all of the base functionality of Hardhat that EVM developers are accustomed to.
While SolidityX compiler support is not explicitly required for this tutorial, we'll go through the process of installing it for future use.
mkdir deploy-simple-quai-contract
cd deploy-simple-quai-contract
npm init
Running npm init will prompt you to name your project and configure a few other variables.
Install Hardhat by running:
npm install --save-dev [email protected]:dominant-strategies/quai-hardhat.git
Install dependencies:
npm install dotenv [email protected]
Initialize the Hardhat development process using:
npx hardhat
After running this command, Hardhat will output a number of options below:
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.17.2
? What do you want to do? …
❯ Create a Javascript project
Create a TypeScript project
Create an empty hardhat.config.js
For this article, we will select the Create a Javascript project option. This will provide you with a preset basic Hardhat project structure with simple smart contracts, tests, and example scripts written in Javascript.
Selecting this option allows you to automatically install @nomicfoundation/hardhat-toolbox.

Smart Contracts

The Create a Javascript project setup option provides a sample contract named Lock.sol. In this tutorial, we're going to deploy a simpler contract example named Greeter.sol.
The Greeter.sol contract requires
In the contracts folder, create a file named Greeter.sol and paste the following code into it.
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.9;
contract Greeter {
string private greeting;
constructor(string memory _greeting) {
greeting = _greeting;
function greet() public view returns (string memory) {
return greeting;
function setGreeting(string memory _greeting) public {
greeting = _greeting;
The Greeter.sol contract allows the deployer to initialize a contract with a greeting stored on-chain, retrieve the greeting string, and change the greeting as needed.

Environment Variables

To prevent committing your private keys or RPC endpoints, create an environment file to securely store variables. Ensure that .env is in your .gitignore.
Use the following command to create an environment file:
touch .env
After creating the .env file, paste the following code into it.
## Sample environment file - change all values as needed
# Privkey
RPCURL="http://localhost:8610" # Cyprus1 URL
You can define your RPCURL with either a local or remote endpoint. Information on endpoints can be found on the Node Overview page for local nodes and the Network Specification page for remote nodes.
After providing a private key and a desired RPC URL, we're now ready to securely consume them inside of hardhat.config.js.

Hardhat Configuration

Hardhat uses hardhat.config.js to configure smart contract deployments. The config file allows you to define deployment networks, tasks, compilers, etc.
Paste the following code into your hardhat.config.js file to configure deployments to either the colosseum, garden, or local networks.
* @type import('hardhat/config').HardhatUserConfig
const dotenv = require('dotenv');
dotenv.config({ path: '.env' });
module.exports = {
defaultNetwork: "colosseum",
networks: {
// testnet
colosseum: {
url: `${process.env.RPCURL}`,
accounts: [process.env.PRIVKEY],
chainId: 9000, // colosseum chainId
// devnet
garden: {
url: `${process.env.RPCURL}`,
accounts: [process.env.PRIVKEY],
chainId: 12000, // garden chainId
// local
local: {
url: `${process.env.RPCURL}`,
accounts: [process.env.PRIVKEY],
chainId: 1337, // local chainId
// include compiler version defined in your smart contract
solidity: {
compilers: [
version: '0.8.9',
paths: {
sources: "./contracts",
cache: "./cache",
artifacts: "./artifacts",
mocha: {
timeout: 20000,


Compile with Hardhat

Smart contract compilation with Hardhat is simple and can be done using npx in the CLI.
If you've used Hardhat before in this directory, you'll need to reset your compilers before compiling any SolidityX based contracts. You can do this by running:
npx hardhat clean --global
Now that we've reset our compilers (or not if you have a clean install of Hardhat), we can go ahead and compile the Greeter.sol contract using:
npx hardhat compile
Which should output:
Downloading compiler 0.8.9
Downloading Solidity X from
Compiled 1 Solidity file successfully
Quai-hardhat will automatically download the SolidityX compiler on first compile, regardless of whether the contract you're compiling utilizes it.

Add Deployment Script

The Hardhat sample project has a pre-made deployment script named deploy.js in the scripts directory. Copy the following into the deploy.js file.
const quais = require('quais');
const hre = require('hardhat');
async function main() {
const ethersContract = await hre.ethers.getContractFactory('Greeter');
const quaisProvider = new quais.providers.JsonRpcProvider(;
const walletWithProvider = new quais.Wallet([0], quaisProvider);
await quaisProvider.ready;
const QuaisContract = new quais.ContractFactory(
const quaisContract = await QuaisContract.deploy('Hello', {
gasLimit: 1000000
await quaisContract.deployed();
console.log('Deployed at:', quaisContract.address);
.then(() => process.exit(0))
.catch((error) => {
Using deploy.js, we can set the initial greeting and log out the contract address upon deployment. Scripts can be used to automate many different functions other than deployment.

Deploy Your Contract

To deploy Greeter.sol to the local network set in your hardhat.config.js, run:
npx hardhat run scripts/deploy.js --network local
Which should output:
Found address 0x0f12d55D09D5E53DB2941a6119d27aa83cFD11f7 on shard zone-0-0 for shard zone-0-0
Deploying contract with address: [object Object]
Deployed at: 0x13d8c5fc0AB5A87870353f3C0409c102f2a772A9
Congratulations, you've now deployed a simple smart contract to Quai Network!

Interact with a Smart Contract

Hardhat console does not currently offer support for interaction with smart contracts on Quai Network. In order to interact with your smart contract, you'll need to utilize the the client JSON RPC or quais.js library, which functions similar to ethers.js.


Now you have all the tools you need to launch a local instance of Quai Network, create a simple Hardhat project, deploy, and interact with your own smart contracts.