> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy with Solidity

> A guide to deploying a simple single-chain smart contract on Quai Network.

## Introduction

This article shows how to deploy a Solidity smart contract using Hardhat on any of Quai Network's chains.

## Prerequisites

To deploy single chain smart contracts on Quai, we'll need a few tool-kits and dependencies. Here's an overview of all of the dependencies we'll be using:

|                                                                                                  |                                                                                                  |
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| [**NodeJS**](https://nodejs.org/en/download/)                                                    | Javascript runtime environment. Use the LTS version.                                             |
| [**hardhat-example**](https://github.com/dominant-strategies/hardhat-example)                    | A Hardhat project with sample contracts and deploy scripts for Quai Network.                     |
| [**Quais.js**](https://www.npmjs.com/package/quais)                                              | A JavaScript library for interacting with Quai Network.                                          |
| [**@quai/hardhat-deploy-metadata**](https://www.npmjs.com/package/@quai/hardhat-deploy-metadata) | A Hardhat plugin that pushes contract metadata to IPFS so contracts can be verified on Quaiscan. |
| [**@openzeppelin/contracts**](https://www.npmjs.com/package/@openzeppelin/contracts)             | Smart contract library used by the sample ERC20 and ERC721 contracts.                            |

## Environment Setup

### Install Example Repository

Start by cloning the `hardhat-example` repository, navigating to the `Solidity` directory we'll be using for this tutorial, and installing the dependencies via `npm`.

```bash theme={null}
git clone https://github.com/dominant-strategies/hardhat-example.git
cd hardhat-example/Solidity
npm install
```

### Smart Contracts

The `Solidity/` directory comes with 2 sample contracts: `ERC20.sol` and `ERC721.sol` inside of the `contracts/` directory. Both contracts are implementations derived from the [Open Zeppelin library](https://www.openzeppelin.com/contracts).

We'll be using the `ERC20.sol` sample contract for this tutorial, but you can also add your own contracts or use contracts from other libraries.

<Warning>
  The Quai Network EVM supports Solidity versions up to 0.8.20. Using a newer
  version of Solidity may result in errors when deploying smart contracts.
</Warning>

### Environment Variables

We've included a sample environment file, `.env.dist`, file at the root of the `hardhat-example` repo to manage token details, private keys, and your RPC URL in a secure fashion.

<Note>
  The `.env.dist` file is a template file and should not be used as is. You should copy the `.env.dist` file to a new `.env` file.

  This file lives at the root of the `hardhat-example` repository and serves as the config file for the `Solidity/` directory.
</Note>

Copy the `.env.dist` file in the root to a new `.env` file in the repository root using the following command:

```bash theme={null}
cp ../.env.dist ../.env
```

Open the `.env` file and add your private key, RPC URL, and token args for the contract you'd like to deploy. The `.env` file should look like this:

```bash .env theme={null}
## Sample environment file - change all values as needed

# Unique privkey for the deployment address
CYPRUS1_PK="0x0000000000000000000000000000000000000000000000000000000000000000" # pubkey starting with 0x00

# Chain ID (local: 1337, Orchard testnet: 15000, mainnet: 9)
CHAIN_ID="15000"

# RPC endpoint
RPC_URL="https://orchard.rpc.quai.network"

# ERC20 Arguments
ERC20_NAME="TestERC20"
ERC20_SYMBOL="TE20"
ERC20_INITIALSUPPLY=1000000

# ERC721 Arguments
ERC721_NAME="TestERC721"
ERC721_SYMBOL="TE721"
ERC721_BASE_URI="ipfs://METADATA_CID/"
ERC721_MAX_TOKENS=1000
```

<Note>
  The sample `.env.dist` targets **Orchard testnet** so you can deploy without
  spending real QUAI. To deploy to mainnet, change `CHAIN_ID` to `9` and
  `RPC_URL` to `https://rpc.quai.network`.
</Note>

Further information on RPC endpoints can be found on the [Networks](/build/networks) page.

The `hardhat-example` repository uses the [Quais SDK](/sdk/introduction) to configure network connections using only a single RPC URL. To learn more about how the SDK configures network providers, visit the [SDK provider examples](/sdk/static/provider) section.

After filling in your private key and RPC URL, we're now ready to securely consume them inside of `hardhat.config.js`.

### Hardhat Configuration

Hardhat uses a `hardhat.config.js` file to configure smart contract deployments. The config file allows you to define deployment networks, tasks, compilers, etc.

`hardhat-example` contains a prebuilt `hardhat.config.js` file with configuration for deploying and verifying smart contracts on Cyprus-1.

<Accordion title="Sample hardhat configuration file" icon="file" iconType="solid">
  This sample configuration file is provided as part of the `hardhat-example` repository.

  ```javascript hardhat.config.js theme={null}
  /**
   * @type import('hardhat/config').HardhatUserConfig
   */

  require('@nomicfoundation/hardhat-toolbox')
  require('@quai/quais-upgrades')
  require('@quai/hardhat-deploy-metadata')

  const dotenv = require('dotenv')
  dotenv.config({ path: '../.env' })

  module.exports = {
    defaultNetwork: 'cyprus1',
    networks: {
      cyprus1: {
        url: process.env.RPC_URL,
        accounts: [process.env.CYPRUS1_PK],
        chainId: Number(process.env.CHAIN_ID),
      },
    },

    solidity: {
      compilers: [
        {
          version: '0.8.17',
          settings: {
            optimizer: { enabled: true, runs: 1000 },
            metadata: {
              bytecodeHash: 'ipfs',
              useLiteralContent: true,
            },
            evmVersion: 'london',
          },
        },
        {
          version: '0.8.20',
          settings: {
            optimizer: { enabled: true, runs: 1000 },
            metadata: {
              bytecodeHash: 'ipfs',
              useLiteralContent: true,
            },
            evmVersion: 'london',
          },
        },
      ],
    },

    paths: {
      sources: './contracts',
      cache: './cache',
      artifacts: './artifacts',
    },
    mocha: {
      timeout: 20000,
    },
  }
  ```

  <Info>
    Cyprus-1 is currently the only active zone on Quai Network, so the sample
    config defines a single `cyprus1` network. See [Networks](/build/networks)
    for the full list of zone endpoints.
  </Info>

  <Warning>
    The `metadata.bytecodeHash: 'ipfs'` and `useLiteralContent: true` compiler
    settings are required for `@quai/hardhat-deploy-metadata` to produce
    verifiable output. Removing them will break Quaiscan verification.
  </Warning>
</Accordion>

When deploying a contract, `hardhat.config.js` pulls your private key and RPC URL from the `.env` file. You can also specify the Solidity version and compiler settings in the `solidity` object.

## Deploy and Interact

<Steps>
  <Step title="Compile with Hardhat">
    Smart contract compilation with Hardhat is simple and can be done using `npx` in the CLI.

    Compile all of the contracts inside the `contracts/` directory with:

    ```bash theme={null}
    npx hardhat compile
    ```

    Which should output:

    ```bash theme={null}
    Downloading compiler 0.8.20

    Compiled 2 Solidity files successfully
    ```
  </Step>

  <Step title="Configure deployment scripts">
    Inside the `scripts/` directory, you'll find a deploy script for both the ERC20 and ERC721 contracts: `deployERC20.js` and `deployERC721.js`. For this tutorial, we'll be deploying an ERC20 contract.

    The `deployERC20.js` script pulls your network configuration from `hardhat.config.js` and your token arguments from the `.env` file at the root of the repository and uses them to deploy your contract.

    Token arguments are consumed via the `tokenArgs` array:

    ```js theme={null}
    const tokenArgs = [process.env.ERC20_NAME, process.env.ERC20_SYMBOL, quais.parseUnits(process.env.ERC20_INITIALSUPPLY)]
    ```

    Before the contract is deployed, the script uses the `@quai/hardhat-deploy-metadata` plugin to push the compiled contract's metadata to IPFS and returns the resulting CID:

    ```js theme={null}
    const { deployMetadata } = require("hardhat")
    // ...
    const ipfsHash = await deployMetadata.pushMetadataToIPFS("ERC20")
    ```

    The CID is then passed as the fourth argument to `ContractFactory`, which embeds it in the deployed bytecode. Quaiscan reads that CID later to fetch your source for verification — without it, the contract can be deployed but not verified.

    ```js theme={null}
    const provider = new quais.JsonRpcProvider(hre.network.config.url, undefined, { usePathing: true })
    const wallet = new quais.Wallet(hre.network.config.accounts[0], provider)
    const ERC20 = new quais.ContractFactory(ERC20Json.abi, ERC20Json.bytecode, wallet, ipfsHash)
    ```

    We'll use these ideas to properly modify the token args and network specification to deploy our contract in the next step.

    <Tip>
      The `deployERC721.js` script follows the same structure with different
      contract arguments and a different ABI/bytecode. You can replicate this
      configuration for any contract you'd like to deploy.
    </Tip>
  </Step>

  <Step title="Deploy your contract">
    The deploy script takes in a `--network` flag to specify the network you'd like to deploy to. The sample config only defines `cyprus1`, which we'll use here.

    ```bash theme={null}
    npx hardhat run scripts/deployERC20.js --network cyprus1
    ```

    Which should output:

    ```bash theme={null}
    File added with CID: QmPCoBa1bCFmRoTD7GuexJqBAy7pqg8J4b8B48q5DgxUEV
    Original IPFS hash found in bytecode: QmPCoBa1bCFmRoTD7GuexJqBAy7pqg8J4b8B48q5DgxUEV
    Metadata JSON for ERC20 saved to /.../hardhat-example/Solidity/metadata/ERC20_metadata.json
    Transaction broadcasted: 0x235fdeb85db5b6cee8da9780e2246907e8342751849f5ce3514847a5dffd916f
    Contract deployed to:  0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC
    ```

    The `CID` printed in the first line is the IPFS hash you'll need to verify the contract on Quaiscan — save it.

    Congratulations, you've now deployed an ERC20 token to Quai Network!

    <Warning>
      The `ERC20.sol` and `ERC721.sol` sample contracts are basic implementations of each token for example purposes. It is highly recommended
      to modify these contracts to fit your specific use case before deploying them for any production use.
    </Warning>
  </Step>

  <Step title="Interact with the contract">
    Hardhat console does not currently offer support for interaction with smart contracts on Quai Network.

    To interact with the contract, you can configure a simple script using the [Quais SDK](/sdk/static/contract). The script below configures a [Contract](/sdk/content/classes/Contract) instance for the ERC20 token we deployed to `0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC` to get the name, symbol, and total supply of the token.

    ```javascript getContractDetails.js theme={null}
    const quais = require('quais')
    const ERC20Json = require('../artifacts/contracts/ERC20.sol/ERC20.json')

    async function getContractDetails() {
      // Config provider, wallet, and contract factory
      const provider = new quais.JsonRpcProvider(hre.network.config.url, undefined, { usePathing: true })
      const wallet = new quais.Wallet(hre.network.config.accounts[0], provider)
      const ERC20 = new quais.Contract("0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC", ERC20Json.abi, wallet)

      const tokenName = await ERC20.name()
      const tokenSymbol = await ERC20.symbol()
      const tokenDecimals = await ERC20.decimals()
      const tokenTotalSupply = await ERC20.totalSupply()
    }

    getContractDetails()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error)
        process.exit(1)
      })
    ```
  </Step>
</Steps>

## Summary

Now you have all the tools you need to create a simple Hardhat project, deploy, and interact with your own smart contracts.

Because the deploy script pushed your contract's metadata to IPFS, you can now verify it on Quaiscan — see [Verifying Contract on Quaiscan](/guides/development/verifycontract) for the next step.
