# Hardhat简洁教程

By [lolieatapple](https://paragraph.com/@lolieatapple) · 2022-08-17

---

1\. 概述
------

HardHat为开发者提供了许多合约开发的便捷功能，包括合约的编译、部署、验证、调试等方面。相对于使用其它工具，使用HardHat进行智能合约开发，可以：

*   方便的启动内置模拟节点；
    
*   使用内置打印接口在solidity代码内打印调试日志(console.log)
    
*   在合约报错查看call-stack，和详细报错原因
    
*   fork现有网络和状态来启动模拟节点
    

2\. 开发环境搭建
----------

可以使用npm install将hardhat工具嵌入到任意现有的solidity工程代码目录内，或者创建全新的工程代码，使用如下代码在空目录中创建全新的solidity合约开发目录框架：

    $ yarn add -D hardhat
    $ yarn hardhat init
    

初始化完成后，目录结构如下：

    .
    ├── README.md
    ├── contracts
    │   └── Lock.sol
    ├── hardhat.config.js
    ├── package.json
    ├── scripts
    │   └── deploy.js
    ├── test
    │   └── Lock.js
    └── yarn.lock
    

contracts目录放置solidity合约代码，scripts目录放置部署脚本test目录放置测试脚本。

3\. Fork现有区块链网络
---------------

使用Fork功能可以基于现有区块链网络RPC创建一个模拟的开发节点。这里的RPC推荐使用Alchemy提供的节点服务。

例如使用下面代码fork一个ethereum的主网开发环境：

(暂时不支持Wanchain，因为不识别transaction type: 255)

    $ yarn hardhat node --fork https://eth-mainnet.g.alchemy.com/v2/<YouAlchemyApiKey>
    

也可在后方加入 **\--fork-block-number 14390000** 参数来指定基于某一个块的状态来进行fork。

fork成功后，它会自动注入20个包含10000ETH的开发账号。同时包含以太坊的所有合约以及地址状态信息。

fork后的默认的RPC是： [http://localhost:8545](http://localhost:8545)

chainId会发生变化，可以在添加到MetaMask的时候看到新chainId。（我本地当前是31337)

将fork节点添加到MetaMask网络，并将生成的测试私钥导入MetaMask钱包中，方便下一步开发使用。

4\. 使用remix开发和调试
----------------

为方便代码部署和调试，这里使用remix绑定本地文件目录功能，绑定刚刚建好的hardhat目录。使用如下指令绑定当前目录到remix：（remixd需要使用npm全局安装）

    $ remixd -s .
    

在浏览器中打开：

[https://remix.ethereum.org/](https://remix.ethereum.org/)

在workspace位置选择localhost，即可连接到本地绑定目录，并看到我们的实例代码文件。

![remix界面截图](https://storage.googleapis.com/papyrus_images/9364b4355a79dda6f1608c781796d79bc7b5f24d6052dd907916c9cc24c4865c.png)

remix界面截图

可以看到Lock.sol中的示例代码。我们在其中加入两行console.log日志打印，并在编译窗口选择合适的solidity版本进行编译。

![编译合约](https://storage.googleapis.com/papyrus_images/d8a56b918da69e3f340b95f02230cad43a7efedabfdf605d2e64cc0c3689d3b5.png)

编译合约

在合约部署页面，选择使用MetaMask部署。

![合约部署](https://storage.googleapis.com/papyrus_images/4436f7acd4a32d8809095e7e03e14e3c2c9da2c469173049d36d438dead0b321.png)

合约部署

输入错误的构造函数参数时，可以在控制台的fork节点日志中看到错误提示信息：

![错误信息提示](https://storage.googleapis.com/papyrus_images/dddb1ee6efadfb1d2648de7da4023ba63d437ca6f5f638238ae1465eadb41ee4.png)

错误信息提示

输入正确的构造函数部署合约，可以在控制台中看到在合约代码中console.log输出的日志信息：

![日志输出](https://storage.googleapis.com/papyrus_images/ec36308690ab728a40fe41b0b58e612f4fe5dbe3935f6c426d603d51b85aa201.png)

日志输出

5\. 使用VSCode + 脚本编译和部署合约
------------------------

编译合约代码可以使用如下指令：

    $ yarn hardhat compile
    

使用本地fork节点部署合约：

    yarn hardhat run --network localhost scripts/deploy.js
    

这里的deploy.js是hardhat自带的实例代码，可根据自己需要任意修改。在fork节点的控制台窗口中可以看到部署成功的合约地址日志信息。

仿照示例代码编写一个withdraw.js，并使用如下指令执行：

    const hre = require("hardhat");
    
    async function main() {
      const Lock = await hre.ethers.getContractFactory("Lock");
      const lock = await Lock.attach("0xcbbe2a5c3a22be749d5ddf24e9534f98951983e2")
      const tx = await lock.withdraw();
      console.log(tx);
    }
    
    // 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;
    });
    

    yarn hardhat run --network localhost scripts/withdraw.js
    

如果执行成功，可以看到执行结果输出，如果执行失败，可以看到失败的具体原因显示。如果有多层级的函数调用，在失败时，可以看到call-stack调用堆栈，方便定位问题所在位置。（注意：调用堆栈功能在remix中不可用）

![call-stack显示](https://storage.googleapis.com/papyrus_images/ffeefdd769ffdecf38b4ee9dd3c4968ef911a24161e624e99fbb36e4a1e10dd9.png)

call-stack显示

6\. 详细参数配置
----------

通过修改hardhat.config.js可以对编译参数进行详细配置，包括但不限于网络信息、solidity版本与优化信息、部署账户信息等。

    module.exports = {
      defaultNetwork: "rinkeby",
      networks: {
        hardhat: {
        },
        rinkeby: {
          url: "https://eth-rinkeby.alchemyapi.io/v2/123abc123abc123abc123abc123abcde",
          accounts: [privateKey1, privateKey2, ...]
        }
      },
      solidity: {
        version: "0.5.15",
        settings: {
          optimizer: {
            enabled: true,
            runs: 200
          }
        }
      },
      paths: {
        sources: "./contracts",
        tests: "./test",
        cache: "./cache",
        artifacts: "./artifacts"
      },
      mocha: {
        timeout: 40000
      }
    }
    

参考链接
----

[https://hardhat.org/hardhat-network/docs/overview](https://hardhat.org/hardhat-network/docs/overview)

[https://hardhat.org/hardhat-runner/docs/getting-started#overview](https://hardhat.org/hardhat-runner/docs/getting-started#overview)

---

*Originally published on [lolieatapple](https://paragraph.com/@lolieatapple/hardhat)*
