跳转至主要内容

Waffle:使用 Hardhat 和 ethers 的“hello world”教程

waffle
智能合同
Solidity
测试
hardhat
ethers.js
初学者
MiZiet
2020年10月16日
5 分钟阅读

在本 Waffleopens in a new tab 教程中,我们将学习如何使用 hardhatopens in a new tabethers.jsopens in a new tab 建立一个简单的“Hello world”智能合约项目。 然后我们将学习如何向我们的智能合约中添加一个新功能,以及如何使用 Waffle 测试它。

让我们从创建新项目开始:

yarn init

npm init

并安装所需的软件包:

yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai

npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai

下一步是通过运行 npx hardhat 创建一个 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
👷 欢迎来到 Hardhat v2.0.3 👷‍
? 你想做什么?…
❯ 创建一个示例项目
创建一个空的 hardhat.config.js
退出
显示全部

选择 Create a sample project(创建示例项目)。

我们的项目结构应如下所示:

1MyWaffleProject
2├── contracts
3│ └── Greeter.sol
4├── node_modules
5├── scripts
6│ └── sample-script.js
7├── test
8│ └── sample-test.js
9├── .gitattributes
10├── .gitignore
11├── hardhat.config.js
12└── package.json
显示全部

现在让我们来谈谈其中一些文件:

  • Greeter.sol - 我们用 Solidity 编写的智能合约;
1contract Greeter {
2string greeting;
3
4constructor(string memory _greeting) public {
5console.log("Deploying a Greeter with greeting:", _greeting);
6greeting = _greeting;
7}
8
9function greet() public view returns (string memory) {
10return greeting;
11}
12
13function setGreeting(string memory _greeting) public {
14console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
15greeting = _greeting;
16}
17}
显示全部

我们的智能合约可以分为三个部分:

  1. 构造函数 - 我们在其中声明一个名为 greeting 的字符串类型变量,
  2. 函数 greet - 调用时将返回 greeting 的函数,
  3. 函数 setGreeting - 允许我们更改 greeting 值的函数。
  • sample-test.js - 我们的测试文件
1describe("Greeter", function () {
2 it("Should return the new greeting once it's changed", async function () {
3 const Greeter = await ethers.getContractFactory("Greeter")
4 const greeter = await Greeter.deploy("Hello, world!")
5
6 await greeter.deployed()
7 expect(await greeter.greet()).to.equal("Hello, world!")
8
9 await greeter.setGreeting("Hola, mundo!")
10 expect(await greeter.greet()).to.equal("Hola, mundo!")
11 })
12})
显示全部

下一步是编译我们的合约并运行测试:

Waffle 测试使用 Mocha(测试框架)与 Chai(一个断言库)。 你只需运行 npx hardhat test 并等待以下消息出现即可。

✓ Should return the new greeting once it's changed

到目前为止,一切看起来都很好,让我们为我们的项目增加一些复杂性吧

想象一下这种情况,有人添加了一个空字符串作为问候语。 那可不是个热情的问候,对吧?
我们来确保这种情况不会发生:

当有人传入空字符串时,我们希望使用 Solidity 的 revert。 好在我们可以用 Waffle 的 chai 匹配器 to.be.revertedWith() 轻松测试这个功能。

1it("Should revert when passing an empty string", async () => {
2 const Greeter = await ethers.getContractFactory("Greeter")
3 const greeter = await Greeter.deploy("Hello, world!")
4
5 await greeter.deployed()
6 await expect(greeter.setGreeting("")).to.be.revertedWith(
7 "Greeting should not be empty"
8 )
9})
显示全部

看来我们的新测试没有通过:

Deploying a Greeter with greeting: Hello, world!
Changing greeting from 'Hello, world!' to 'Hola, mundo!'
✓ Should return the new greeting once it's changed (1514ms)
Deploying a Greeter with greeting: Hello, world!
Changing greeting from 'Hello, world!' to ''
1) Should revert when passing an empty string
1 passing (2s)
1 failing
显示全部

让我们在智能合约中实现这个功能:

1require(bytes(_greeting).length > 0, "Greeting should not be empty");

现在,我们的 setGreeting 函数如下所示:

1function setGreeting(string memory _greeting) public {
2require(bytes(_greeting).length > 0, "Greeting should not be empty");
3console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
4greeting = _greeting;
5}

让我们再次运行测试:

✓ Should return the new greeting once it's changed (1467ms)
✓ Should revert when passing an empty string (276ms)
2 passing (2s)

恭喜! 你做到了 :)

结论

我们使用 Waffle、Hardhat 和 ethers.js 制作了一个简单的项目。 我们学习了如何设置项目、添加测试和实现新功能。

如需更多用于测试智能合约的出色 chai 匹配器,请查看 Waffle 的官方文档opens in a new tab

页面最后更新: 2023年12月8日

本教程对你有帮助吗?