# 概述

Hardhat是一个编译、部署、测试和调试以太坊应用的开发环境。它可以帮助开发人员管理和自动化构建智能合约和dApps过程中固有的重复性任务,并围绕这一工作流程轻松引入更多功能。这意味着hardhat在最核心的地方是编译、运行和测试智能合约。

Hardhat内置了Hardhat网络,这是一个专为开发设计的本地以太坊网络。主要功能有Solidity调试,跟踪调用堆栈、console.log()和交易失败时的明确错误信息提示等。

Hardhat Runner是与Hardhat交互的CLI命令,是一个可扩展的任务运行器。它是围绕任务插件的概念设计的。每次你从CLI运行Hardhat时,你都在运行一个任务。例如,npx hardhat compile运行的是内置的compile任务。任务可以调用其他任务,允许定义复杂的工作流程。用户和插件可以覆盖现有的任务,从而定制和扩展工作流程。

Hardhat的很多功能都来自于插件,而作为开发者,你可以自由选择想使用的插件。Hardhat不限制使用什么工具的,但它确实有一些内置的默认值。所有这些都可以覆盖。

# 安装

Hardhat是通过本地安装在项目中使用的。这样你的环境就可以重现,也可以避免未来的版本冲突。

要安装它,你需要创建一个npm项目,进入一个空文件夹,运行npm init。 并遵循其指示操作。项目初始化之后,运行:

npm install --save-dev hardhat

要使用本地安装的Hardhat,需要使用npx来运行它(如:npx hardhat)。

# 快速开始

本指南将探讨创建Hardhat项目的基础知识。

Hardhat即使在没有安装插件下,你也能创建自己的任务,编译Solidity代码,运行测试,并运行Hardhat Network,你可以将合约部署到本地开发网络。

通过在项目文件夹中运行npx hardhat来创建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.0.8

? What do you want to do? …
❯ Create a sample project
  Create an empty hardhat.config.js
  Quit

我们选择创建示例项目,并通过逐个步骤来演示样本任务和编译、测试、并部署样本合约。

示例项目会要求安装hardhat-wafflehardhat-ethers,以便让Hardhat与Waffle构建的测试兼容。你可以这个指南中了解更多信息。

TIP

Hardhat会让提示你如何安装,但是,如果你错过了,你可以用npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers来安装它们。

# 运行任务

在项目文件夹中运行npx hardhat,可以快速了解可用的命令和任务:

$ npx hardhat
Hardhat version 2.0.8

Usage: hardhat [GLOBAL OPTIONS] <TASK> [TASK OPTIONS]

GLOBAL OPTIONS:

  --config              A Hardhat config file.
  --emoji               Use emoji in messages.
  --help                Shows this message, or a task's help if its name is provided
  --max-memory          The maximum amount of memory that Hardhat can use.
  --network             The network to connect to.
  --show-stack-traces   Show stack traces.
  --tsconfig            Reserved hardhat argument -- Has no effect.
  --verbose             Enables Hardhat verbose logging
  --version             Shows hardhat's version.


AVAILABLE TASKS:

  accounts      Prints the list of accounts
  check         Check whatever you need
  clean         Clears the cache and deletes all artifacts
  compile       Compiles the entire project, building all artifacts
  console       Opens a hardhat console
  flatten       Flattens and prints contracts and their dependencies
  help          Prints this message
  node          Starts a JSON-RPC server on top of Hardhat Network
  run           Runs a user-defined script after compiling the project
  test          Runs mocha tests

To get help for a specific task run: npx hardhat help [task]

这是内置任务的列表,当你使用插件来添加更多的功能时,插件定义的任务也会在这里显示。 这是你的出发的起点,在这里了解有哪些任务可以运行。

这里是accounts任务的示例,如果你看一下hardhat.config.js文件,你会发现accounts任务的定义:





 
 
 
 
 
 
 












require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
  const accounts = await ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.7.3",
};

要运行accounts任务,使用 npx hardhat accounts:

$ npx hardhat accounts
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
0x90F79bf6EB2c4f870365E785982E1f101E93b906
0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65
0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc
0x976EA74026E726554dB657fA54763abd0C3a0aa9
0x14dC79964da2C08b23698B3D3cc7Ca32193d9955
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f
0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
0xBcd4042DE499D14e55001CcbB24a551F3b954096
0x71bE63f3384f5fb98995898A86B02Fb2426c5788
0xFABB0ac9d68B0B445fB7357272Ff202C5651694a
0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec
0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097
0xcd3B766CCDd6AE721141F452C550Ca635964ce71
0x2546BcD3c84621e976D8185a91A922aE77ECEc30
0xbDA5747bFD65F08deb54cb465eB87D40e51B197E
0xdD2FD4581271e230360230F9337D5c0430Bf44C0
0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199

# 编译合约

接下来,如果你看一下contracts/,应该可以找到Greeter.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.7.0;

import "hardhat/console.sol";


contract Greeter {
  string greeting;

  constructor(string memory _greeting) {
    console.log("Deploying a Greeter with greeting:", _greeting);
    greeting = _greeting;
  }

  function greet() public view returns (string memory) {
    return greeting;
  }

  function setGreeting(string memory _greeting) public {
    console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
    greeting = _greeting;
  }
}

要编译它,只需运行:

npx hardhat compile

# 测试合约

当前的示例项目使用Waffle(opens new window) Ethers.js(opens new window) 进行测试。如果你想的话,也可以使用其他的代码库。

test/目录下,可以找到sample-test.js文件:

const { expect } = require("chai");

describe("Greeter", function() {
  it("Should return the new greeting once it's changed", async function() {
    const Greeter = await ethers.getContractFactory("Greeter");
    const greeter = await Greeter.deploy("Hello, world!");
    
    await greeter.deployed();
    expect(await greeter.greet()).to.equal("Hello, world!");

    await greeter.setGreeting("Hola, mundo!");
    expect(await greeter.greet()).to.equal("Hola, mundo!");
  });
});

你可以使用npx hardhat test来运行测试:

$ npx hardhat test
Compiling 1 file with 0.7.3
Compilation finished successfully


  Greeter
Deploying a Greeter with greeting: Hello, world!
Changing greeting from 'Hello, world!' to 'Hola, mundo!'
    ✓ Should return the new greeting once it's changed (803ms)


  1 passing (805ms)

# 部署合约

接下来,我们使用Hardhat脚本部署合约。 在 scripts/里面,你会发现 sample-script.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>`.
//
// When running the script with `hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const hre = require("hardhat");

async function main() {
  // Hardhat always runs the compile task when running scripts with its command
  // line interface.
  //
  // If this script is run directly using `node` you may want to call compile 
  // manually to make sure everything is compiled
  // await hre.run('compile');

  // We get the contract to deploy
  const Greeter = await hre.ethers.getContractFactory("Greeter");
  const greeter = await Greeter.deploy("Hello, Hardhat!");

  await greeter.deployed();

  console.log("Greeter deployed to:", greeter.address);
}

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

npx hardhat run scripts/sample-script.js运行它:

$ npx hardhat run scripts/sample-script.js
Deploying a Greeter with greeting: Hello, Hardhat!
Greeter deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3

# 连接钱包或Dapp到Hardhat网络

Hardhat在启动时,默认情况下总会启动一个Hardhat Network的内存实例,你也可以以独立的方式运行Hardhat Network,以便外部客户(可能是MetaMask,你的Dapp前端,或者一个脚本)可以连接到它。

要以独立的方式运行Hardhat Network,运行npx hardhat node:

$ npx hardhat node
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

这将暴露一个JSON-RPC接口链接到Hardhat网络。只要将钱包或应用程序连接到http://localhost:8545就可以使用它。

如果要把Hardhat连接到这个节点上,例如,要在这个网络上运行一个部署脚本,只需要使用--network localhost来运行脚本。

你可以试一试,先用npx hardhat node启动一个节点,并使用network参数重新运行示例脚本:

npx hardhat run scripts/sample-script.js --network localhost

恭喜你,你已经创建了一个项目,运行了一个Hardhat任务,编译了一个智能合约,安装了一个Waffle插件,使用Waffle和ethers.js插件编写并运行了一个测试,并部署了一个合约。

如果你有任何问题或反馈,你可以在Hardhat Discord(opens new window) 找到我们。

Last Updated: 4/19/2021, 10:58:33 AM