> 技术文档 > 区块链之以太坊Hardhat开发框架——部署在windows为例

区块链之以太坊Hardhat开发框架——部署在windows为例

Hardhat 提供了一个灵活且易于使用的开发环境,可以轻松地编写、测试和部署智能合约。Hardhat还内置了Hardhat 网络(Hardhat Node),它是为开发而设计的本地以太坊网络。

下面是hardhat的官方文档

https://hardhat.org/hardhat-runner/docs/getting-started

一、创建及配置Hardhat项目

Hardhat 构建在 Node.js 之上, 使用 Hardhat 要求我们在电脑先安装好Node.js (>= 16.0),创建hardhat-tutorial文件夹。

1、初始化Node项目

2、安装Hardhat 

 3、运行hardhat

用键盘选择create a JavaScript project

生成project后的项目目录 

二、编写合约 

合约开发推荐使用 VSCode 编辑器 + solidity 插件,在VSCode下添加solidity插件

contracts 文件夹下新建一个合约文件 Counter.sol

Counter.js代码如下: 

//SPDX-License-Identifier: MITpragma solidity ^0.8.0;contract Counter { uint counter; constructor() { counter = 0; } function count() public { counter = counter + 1; } function get() public view returns (uint) { return counter; }}

 在编写合约时,尽量不要重复造轮子,基于优质开源的第三方库,不仅可以提高效率,还可以让我们的合约代码更安全,例如要开发一个 Token,可以用npm 安装OpenZepplin 库:

npm install @openzeppelin/contracts --save-dev

然后在合约中 import 相应库中的合约文件及可。

pragma solidity ^0.8.0;import \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";contract Token is ERC20 { constructor(uint256 initialSupply) ERC20(\"Token Name\", \"Token Symbol\") { _mint(msg.sender, initialSupply); }}

 三、编译合约

hardhat.config.js 有默认的Solidity 编译器配置,因此我们直接编译合约即可,在终端中运行 npx hardhat compile。

成功编译后,会在 artifacts/contracts/ 目录下生成Counter.json 和 build-info, Counter.json包含了智能合约的 ABI 、字节码(Bytecode)等

智能合约的ABI信息,包括了合约的函数、事件等接口信息。这个文件通常会与其他合约交互时使用,因为它可以被其他合约和DApp使用。

Bytecode是部署合约所需的字节码,部署合约时候就是把该字节码作为交易的输入数据发送链上。

 四、编写测试用例

为智能合约编写自动化测试至关重要,因为事关用户资金。

使用 Harhdat 内置的网络,使用ethers.js与前面的合约进行交互,并使用 Mocha 作为测试运行器。在test文件夹下创建Counter.js文件代码如下:

// 引入 Hardhat 提供的 ethers 库,用于部署和交互智能合约const { ethers } = require(\"hardhat\");// 引入 chai 的断言函数 expect,用于编写测试判断条件const { expect } = require(\"chai\");// 定义一个全局变量,用于存储部署后的合约实例let counter;// 定义测试套件,描述被测试的合约模块为 \"Counter\"describe(\"Counter\", function () { // 初始化函数:部署 Counter 合约并获取实例 async function init() { // 获取测试账户数组,其中 owner 是部署者,otherAccount 可用于后续扩展测试权限等 const [owner, otherAccount] = await ethers.getSigners(); // 获取 Counter 合约工厂(ContractFactory),可以用来部署合约 const Counter = await ethers.getContractFactory(\"Counter\"); // 部署合约并返回实例(此时合约已经部署完成,不需要调用 .deployed()) counter = await Counter.deploy(); // 打印部署后合约的地址(ethers v6 中使用 .target 属性获取地址) console.log(\"counter:\" + counter.target); } // 所有测试用例运行前执行一次初始化操作(部署合约) before(async function () { await init(); }); // 第一个测试用例:测试合约初始值是否为 0 it(\"init equal 0\", async function () { // 调用 counter 合约的 get() 方法,断言返回值为 0 expect(await counter.get()).to.equal(0); }); // 第二个测试用例:调用 count() 函数自增,验证是否变为 1 it(\"add 1 equal 1\", async function () { // 调用 count() 方法进行加 1 操作 let tx = await counter.count(); // 等待交易被打包确认 await tx.wait(); // 调用 get() 方法获取当前计数值,断言为 1 expect(await counter.get()).to.equal(1); });});

运行npx hardhat test之后输出全部通过,证明测试通过。 

还可以在Solidity代码中调用console.log()打印日志信息和合约变量,可以方便我们调试代码。

在合约代码中导入Hardhat console.log就可以使用它。

 五、部署合约

部署合约我们需要编写一个部署脚本。

在项目下新建scripts文件夹,新建一个deploy.js 用来写部署脚本,代码如下

const { ethers } = require(\"hardhat\");async function main() { // 获取合约工厂 const Counter = await ethers.getContractFactory(\"Counter\"); // 部署合约(v6 会自动等待部署完成) const counter = await Counter.deploy(); // 输出部署的合约地址(v6 使用 counter.target) console.log(\"Counter address:\", counter.target);}main().catch((error) => { console.error(error); process.exitCode = 1;});

运行 npx hardhat run scripts/deploy.js 时,合约会部署到 Hardhat 内置网络上。 

 为了在运行任何任务时指示Hardhat连接到特定的EVM网络,可以使用--network参数。

npx hardhat run scripts/deploy.js --network 

network-name 需要在 hardhat.config.js 文件中进行配置:

require(\"@nomicfoundation/hardhat-toolbox\");// 填入自己的私钥或助记词,const PRIVATE_KEY1 = \"0x.... YOUR PRIVATE KEY1\";const PRIVATE_KEY2 = \"0x.... YOUR PRIVATE KEY1\";const Mnemonic = \"YOUR Mnemonic\";module.exports = { solidity: \"0.8.9\", // solidity的编译版本 networks: { goerli: { url: \"https://eth-goerli.api.onfinality.io/public\", accounts: [PRIVATE_KEY1,PRIVATE_KEY2], chainId: 5, }, mumbai: { url: \"https://endpoints.omniatech.io/v1/matic/mumbai/public\", accounts: { mnemonic: Mnemonic, }, chainId: 80001, }, }};

以上配置了两个网络,一个是以太坊测试网 goerli, 一个是 Polygon 测试网mumbai, 我们可以在 https://chainlist.org 找到每个网络的节点 URL 及 chainID。

在网络配置中,需要提供提交交易账号, 可以通过私钥或助记词 进行配置,这里配置的账号(需要提前充币进入到账号中),在hardhat 脚本中(测试及部署脚本)调用getSigners 即可获得:

const [owner, otherAccount] = await ethers.getSigners();

六、代码开源验证

智能代码开源会增加了合约的透明度和可靠性,是项目建立信任很重要的一个步骤。

1、安装 hardhat-toolbox 或 hardhat-etherscan , 这一步我们这里已经完成,因为在初始化项目的时候安装了 hardhat-toolbox , 如果没有安装,可以使用以下命令安装

npm install --save-dev @nomiclabs/hardhat-etherscan

2、在hardhat.config.js 中配置您的 Etherscan API 密钥和网络设置,例如: 

     require(\"@nomicfoundation/hardhat-toolbox\"); 或 // require(\"@nomiclabs/hardhat-etherscan\"); etherscan: { apiKey: \"\" }, 

     如何获取 Etherscan API 密钥?

    1. 访问部署网络对应主网的 Etherscan 网站,并注册一个账号(如果还没有账号的话)。
    2. 登录你的账号并进入 Etherscan 的「我的帐户」页面。
    3. 点击页面左侧的「API-KEYs」标签页。
    4. 在页面上方的「Create New API KEY」部分,输入 API 密钥的名称和描述,然后选择需要访问的 API 权限。
    5. 点击「Generate」按钮来生成 API 密钥。

     

    3、执行验证命令:

    npx hardhat verify  \"参数(若有)\" --network  

    该命令会为我们上传合约代码并验证其源代码。如果一切顺利(网络顺畅的话),在 Etherscan 上看到的合约被成功验证。