Skip to content

Using Hardhat to Deploy to Your EVM Appchain

Introduction

Hardhat is an Ethereum development environment that helps developers manage and automate the recurring tasks inherent to building smart contracts and dApps. Hardhat can be used with any EVM appchain to build, compile, and deploy smart contracts, thanks to the seamless compatibility of Tanssi EVM appchains.

This guide will cover how to use Hardhat to compile, deploy, and interact with Ethereum smart contracts deployed to the demo Tanssi EVM appchain. This guide can be adapted for your own Tanssi EVM appchain by simply adding the RPC URL of your Tanssi appchain to your EVM Wallet and switching networks to it.

Checking Prerequisites

For this guide, you'll need to have MetaMask installed and configured to work with your Tanssi EVM appchain. You can follow this guide to configure MetaMask for Tanssi with the demo EVM appchain.

Creating a Hardhat Project

You must create a Hardhat project if you don't already have one. You can create one by completing the following steps:

  1. Create a directory for your project

    mkdir hardhat && cd hardhat
    
  2. Initialize the project, which will create a package.json file

    npm init -y
    
  3. Install Hardhat

    npm install hardhat
    
  4. Create a project

    npx hardhat init
    

    Note

    npx is used to run executables installed locally in your project. Although Hardhat can be installed globally, installing it locally in each project is recommended so you can control the version on a project-by-project basis.

  5. A menu will appear allowing you to create a new project or use a sample project. For this example, you can choose Create an empty hardhat.config.js

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.2 👷‍
 What do you want to do? …   Create a JavaScript project   Create a TypeScript project   Create a TypeScript project (with Viem)   Quit

This will create a Hardhat config file (hardhat.config.js) in your project directory.

Once you have your Hardhat project, you can also install the Ethers plugin. This provides a convenient way to use the Ethers.js library to interact with the network. To install it, run the following command:

npm install @nomicfoundation/hardhat-ethers ethers

Additionally, you'll need to install the hardhat-ignition-ethers plugin to enable deployment of smart contracts with Hardhat Ignition. You can install it with the following command:

npm install --save-dev @nomicfoundation/hardhat-ignition-ethers

The Contract File

With your empty project created, you will create a contracts directory next. You can do so by running the following command:

mkdir contracts && cd contracts

The smart contract that you'll deploy as an example will be called Box, it will let you store a value that can be retrieved later. In the contracts directory, you can create the Box.sol file:

touch Box.sol

Open the file and add the following contract to it:

// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

The Hardhat Configuration File

Before you can deploy the contract to your Tanssi appchain, you'll need to modify the Hardhat configuration file and create a secure file to store your private key in.

You can modify the hardhat.config.js file to use either the Tanssi Dancebox demo EVM appchain or your own Tanssi appchain:

// 1. Import the Ethers and Hardhat Ignition plugins required to interact with the contract
require('@nomicfoundation/hardhat-ethers');
require('@nomicfoundation/hardhat-ignition-ethers');

// 2. Add your private key that is funded with tokens of your Tanssi appchain
// This is for example purposes only - **never store your private keys in a JavaScript file**
const privateKey = 'INSERT_PRIVATE_KEY';

module.exports = {
  // 3. Specify the Solidity version
  solidity: '0.8.1',
  networks: {
    // 4. Add the network specification for your Tanssi EVM appchain
    dancebox: {
      url: 'https://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network',
      chainId: 5678, // Fill in the EVM ChainID for your Tanssi appchain
      accounts: [privateKey]
    }
  }
};

Congratulations! You are now ready for deployment!

Compiling Solidity

To compile the contract you can simply run:

npx hardhat compile
npx hardhat compile Compiled 8 Solidity files successfully (evm target: paris).

After compilation, an artifacts directory is created: it holds the bytecode and metadata of the contract, which are .json files. Adding this directory to your .gitignore is a good idea.

Deploying the Contract

To deploy the contract, you'll use Hardhat Ignition, a declarative framework for deploying smart contracts. Hardhat Ignition is designed to make managing recurring tasks surrounding smart contract deployment and testing easy. For more information, be sure to check out the Hardhat Ignition docs.

To set up the proper file structure for your Ignition module, create a folder named ignition and a subdirectory called modules. Then add a new file to it called Box.js. You can take all three of these steps with the following command:

mkdir ignition ignition/modules && touch ignition/modules/Box.js

Next, you can write your Hardhat Ignition module. To get started, take the following steps:

  1. Import the buildModule function from the Hardhat Ignition module
  2. Export a module using buildModule
  3. Use the getAccount method to select the deployer account
  4. Specify custom gas price and gas limit settings for the deployment
  5. Deploy the Box contract
  6. Return an object from the module. This makes the Box contract accessible for interaction in Hardhat tests and scripts
// 1.  Import the `buildModule` function from the Hardhat Ignition module
const { buildModule } = require('@nomicfoundation/hardhat-ignition/modules');

// 2. Export a module using `buildModule`
module.exports = buildModule('BoxModule', (m) => {
  // 3. Use the `getAccount` method to select the deployer account
  const deployer = m.getAccount(0);

  // 4. Specify custom gas price and gas limit settings for the deployment
  const customGasPrice = 50000000000n;
  const customGasLimit = 1000000;

  // 5. Deploy the `Box` contract using the selected deployer account and custom gas settings
  const box = m.contract('Box', [], {
    from: deployer,
    gasPrice: customGasPrice,
    gasLimit: customGasLimit,
  });

  // 6. Return an object from the module including references to deployed contracts. This makes the deployed `Box` contract accessible for interaction in tests and scripts
  return { box };
});

To run the script and deploy the Box.sol contract, use the following command, which requires you to specify the network name as defined in your hardhat.config.js. Hardhat will deploy the contract to a local hardhat network by default if you don't specify a network.

npx hardhat ignition deploy ./ignition/modules/Box.js --network dancebox

You'll be prompted to confirm the network you wish to deploy to. After a few seconds after you confirm, the contract is deployed, and you'll see the contract address in the terminal. If you're deploying to another Tanssi appchain, make sure that you specify the correct network. The network name must match how it's defined in hardhat.config.js. After a few seconds, the contract is deployed, and you should see the address in the terminal.

npx hardhat ignition deploy ./ignition/modules/Box.js --network dancebox
✅ Confirm deploy to network dancebox (5678)? … yes Hardhat Ignition 🚀
Deploying [ BoxModule ]
Batch #1 Executed BoxModule#Box
[ BoxModule ] successfully deployed 🚀
Deployed Addresses
BoxModule#Box - 0xa84caB60db6541573a091e5C622fB79e175E17be

Congratulations, your contract is live! Save the address, as you will use it to interact with this contract instance in the next step.

Interacting with the Contract

To interact with your newly deployed contract on your Tanssi appchain, you can launch the Hardhat console by running:

npx hardhat console --network dancebox

Next, you can take the following steps, entering one line at a time:

  1. Create a local instance of the Box.sol contract

    const Box = await ethers.getContractFactory('Box');
    
  2. Connect the local instance to the deployed contract, using the address of the contract

    const box = await Box.attach('0xa84caB60db6541573a091e5C622fB79e175E17be');
    
  3. Interact with the attached contract. For this example, you can call the store method and store a simple value

    await box.store(5);
    

Your EVM account will sign the transaction and broadcast it to the network. The output should look similar to:

npx hardhat console --network dancebox
Welcome to Node.js v20.9.0. Type ".help" for more information. const Box = await ethers.getContractFactory('Box'); undefined
const box = await Box.attach('0xa84caB60db6541573a091e5C622fB79e175E17be'); undefined
await box.store(5); ContractTransactionResponse {
provider: HardhatEthersProvider { ... },
blockNumber: null,
blockHash: null,
index: undefined,
hash: '0x1c49a64a601fc5dd184f0a368a91130cb49203ec0f533c6fcf20445c68e20264',
type: 2,
to: '0xa84caB60db6541573a091e5C622fB79e175E17be',
from: '0x3B939FeaD1557C741Ff06492FD0127bd287A421e',
nonce: 87,
gasLimit: 45881n,
gasPrice: 1107421875n,
maxPriorityFeePerGas: 1n,
maxFeePerGas: 1107421875n,
data: '0x6057361d0000000000000000000000000000000000000000000000000000000000000005',
value: 0n,
chainId: 5678n,
signature: Signature { r: "0x9233b9cc4ae6879b7e08b9f1a4bfb175c8216eee0099966eca4a305c7f369ecc", s: "0x7663688633006b5a449d02cb08311569fadf2f9696bd7fe65417860a3b5fc57d", yParity: 0, networkV: null },
accessList: [],
blobVersionedHashes: null
}
await box.retrieve(); 5n

Notice your address labeled from, the contract's address, and the data being passed. Now, you can retrieve the value by running:

await box.retrieve();

You should see 5 or the value you initially stored.

Note

If you run the retrieve command immediately after storing the value, you may see the old value. Rerunning the retrieval command after waiting a moment will return the correct value.

Congratulations, you have successfully deployed and interacted with a contract using Hardhat!

The information presented herein has been provided by third parties and is made available solely for general information purposes. Tanssi does not endorse any project listed and described on the Tanssi Doc Website (https://docs.tanssi.network/). Tanssi Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Tanssi Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Tanssi Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Tanssi Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Tanssi Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
Last update: May 10, 2024
| Created: October 13, 2023