概述
Hardhat 是以太坊软件的开发环境。它是由用于编辑,编译,调试和部署智能合约和dapps的不同组件组成,所有这些组件共同创建一个完整的开发环境。
Hardhat Runner 是您在使用 Hardhat 时与之交互的主要组件。他是一个灵活且可扩展的任务运行器,可帮助管理和自动化开发智能合约和dapp所固有的重复性任务。
开始你的项目
准备工作
1.使用npm初始化项目文件夹
npm init -y
2.下载Hardhat
npm install --save-dev hardhat
(p9-juejin.byteimg.com/tos-cn-i-k3…?)
3.运行hardhat
npx hardhat/*
4.初始化后的目录如下
- contracts/ 该目录存放智能合约源文件
- scripts/ 该目录下存放简单的自动化执行脚本
- test/ 该目录存放测试智能合约代码的文件
编译合约
- 编译合约需要使用hardhat内置的compile任务
编译完成后,若没有出现问题,则会生成两个新文件夹:artifacts/ ,cache/
contracts/下的合约文件编译生成的文件保存在artifacts/目录下
- 配置编译
如果要自定义编译器选项,可以通过hardhat.config.js。设置solidity编译器版本
测试合约
hardhat可以使用JavaScript或者typescript两种语言来测试合约,但是官方建议使用TypeScript来获得更好的自动补全,并尽早捕获可能的错误。本指南使用的是TypeScript。
本文以hardhat自动生成的 test/ 目录下的Lock文件讲解
- 导入配置文件及工具
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
import { expect } from "chai";
import { ethers } from "hardhat";
- 异步函数
lockedAmount表示锁仓金额
unlockTime是锁仓时间
ethers.getSigners()是以太坊账户的抽象,可用于对消息和交易进行签名,并将已签名的交易发送到以太坊网络以执行状态更改操作。
ethers.getContractFactory("Lock")得到合约工厂对象
Lock.deploy(unlockTime, { value: lockedAmount })用合约工厂对象对合约进行部署,部署的参数是构造函数的参数。
async function deployOneYearLockFixture() {
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
const ONE_GWEI = 1_000_000_000;
const lockedAmount = ONE_GWEI;
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
const Lock = await ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
return { lock, unlockTime, lockedAmount, owner, otherAccount };
}
- 测试方法
Describe 是JavaScript中的一个函数测试框架。它简单地描述了由“it”函数枚举的测试用例套件。
以下是合约代码里可能会存在的错误进行测试如:锁仓时间是否一样,是否是owner调用withdraw()方法
1."Should set the right unlockTime" : 比较合约的unlockTime和我们部署所给的是否一样
2."Should set the right owner": 比较 是否是同一个调用者
3."Should receive and store the funds to lock": 调用者地址上的金额是否和锁在合约里面的金额一致
4."Should fail if the unlockTime is not in the future": 测试unlockTime的值不是在未来值是否会报错
describe("Depl oyment", function () {
it("Should set the right unlockTime", async function () {
// loadFixture是让合约回复到初始状态,不需要重复部署。
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
expect(await lock.unlockTime()).to.equal(unlockTime);
});
it("Should set the right owner", async function () {
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
expect(await lock.owner()).to.equal(owner.address);
});
it("Should receive and store the funds to lock", async function () {
const { lock, lockedAmount } = await loadFixture(deployOneYearLockFixture);
expect(await ethers.provider.getBalance(lock.address)).to.equal(lockedAmount);
});
it("Should fail if the unlockTime is not in the future", async function () {
// We don't use the fixture here because we want a different deployment
const latestTime = await time.latest();
const Lock = await ethers.getContractFactory("Lock");
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
"Unlock time should be in the future"
);
});
});
部署合约
在部署方面,目前还没有为 Hardhat 实现部署系统的官方插件。我们使用部署脚本来部署合约。
- 开启一个本地节点,便于本地部署
npx hardhat node
- 重新打开一个终端并在localhost网络中部署合约
npx hardhat run --network localhost scripts/deploy.ts
- 如果不在本地网络中部署,可以选择市面上主网的测试网进行部署
npx hardhat run --network < you network > scripts/deploy.js