Hardhat

Deploy and Execute Smart Contracts using Hardhat

Let`s create and deploy Smart Contracts using Hardhat.

You can create Hardhat project as follows. After running 'npx hardhat', you select what type of project to create and set the the root path for the project. If You choose to add the '.gitignore file' or install the dependency module for the sample project, the necessary files are installed.

$ mkdir greeter
$ cd greeter

$ npm install --save-dev hardhat

$ npx hardhat
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.13.0 👷‍

✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /Users/trident/Projects/Solidity/hardhat-test
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox)? (Y/n) · y

After installation, the directory structure is as follows. Smart contracts will be located in contracts, deployed scripts in scripts, test code in tests, and compiled results in artifacts, cache. Set the network connection information, solidity compiler version information, and so on in hardhat.config.js.

tree . -I node_modules
.
├── README.md
├── contracts
│   └── Lock.sol
├── hardhat.config.js
├── package-lock.json
├── package.json
├── scripts
│   └── deploy.js
└── test
    └── Lock.js

4 directories, 7 files

The Lock.sol that is created by default is compiled as follows.

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

// Uncomment this line to use console.log
// import "hardhat/console.sol";

contract Lock {
    uint public unlockTime;
    address payable public owner;

    event Withdrawal(uint amount, uint when);

    constructor(uint _unlockTime) payable {
        require(
            block.timestamp < _unlockTime,
            "Unlock time should be in the future"
        );

        unlockTime = _unlockTime;
        owner = payable(msg.sender);
    }

    function withdraw() public {
        // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
        // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);

        require(block.timestamp >= unlockTime, "You can't withdraw yet");
        require(msg.sender == owner, "You aren't the owner");

        emit Withdrawal(address(this).balance, block.timestamp);

        owner.transfer(address(this).balance);
    }
}
$ npx hardhat compile
Compiled 1 Solidity files successfully

Run the test using Lock.js, which is created by default.

$ npx hardhat test


  Lock
    Deployment
      ✔ Should set the right unlockTime (2392ms)
      ✔ Should set the right owner
      ✔ Should receive and store the funds to lock
      ✔ Should fail if the unlockTime is not in the future (46ms)
    Withdrawals
      Validations
        ✔ Should revert with the right error if called too soon
        ✔ Should revert with the right error if called from another account
        ✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
      Events
        ✔ Should emit an event on withdrawals
      Transfers
        ✔ Should transfer the funds to the owner


  9 passing (3s)

Deploying smart contracts uses deploy.js, which is provided by default. You need to set up a network to deploy in advance, but add the WEMIX3.0 Testnet and Mainnet to hardhat.config.js as shown below. If you save the private key of the account address that use for deployment, it is easy to work with, so we recommend that you create a test account and then send as many WEMIX as you need. How to extract private keys from a MetaMask is omitted here.

hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
const PrivateKey = "<<Private Key>>"

module.exports = {
  solidity: "0.8.18",
  networks: {
    wemix_testnet: {
      url: "https://api.test.wemix.com",
      accounts: [`0x${PrivateKey}`],
      gasPrice: 101000000000
    },
    wemix_mainnet: {
      url: "https://api.wemix.com",
      accounts: [`0x${PrivateKey}`],
      gasPrice: 101000000000
    },
  },
};
scripts/deploy.js
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
// will compile your contracts, add the Hardhat Runtime Environment's members to the
// global scope, and execute the script.
const hre = require("hardhat");

async function main() {
  const currentTimestampInSeconds = Math.round(Date.now() / 1000);
  const unlockTime = currentTimestampInSeconds + 60;

  const lockedAmount = hre.ethers.utils.parseEther("0.001");

  const Lock = await hre.ethers.getContractFactory("Lock");
  const lock = await Lock.deploy(unlockTime, { value: lockedAmount });

  await lock.deployed();

  console.log(
    `Lock with ${ethers.utils.formatEther(
      lockedAmount
    )}ETH and unlock timestamp ${unlockTime} deployed to ${lock.address}`
  );
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

When you are ready, run the following command to deploy. Upon successful deployment, the smart contract address is output according to the preset log.

$ npx hardhat run scripts/deploy.js --network wemix_testnet
Lock with 0.001ETH and unlock timestamp 1679558487 deployed to 0x813fbbbeF30f343da37332293546dc854

Last updated