Hardhat使用教程
信息
Hardhat是一个基于JavaScript的智能合约开发环境,可以用于灵活的编译、部署、测试和调试基于Solidity编译的EVM智能合约,并提供了一系列的工具来整合代码与外部工具,还提供了丰富的插件生态。Hardhat还提供了本地以太坊节点的Hardhat网络,用来部署合约、运行测试和调试代码。
官方文档:https://hardhat.org/hardhat-runner/docs/getting-started
项目创建
提示
前提:要求Nodejs的版本要>=16.0
创建项目目录
mkdir hardhat-tutorial
cd hardhat-tutorial
初始化Nodejs项目
# -y:表示自动回答所有设置项目信息的问题,而不需要用户手动输入(项目名称、版本、描述、入口文件...),使用默认值填充 package.json 文件。
npm init -y
安装harhat
npm install --save-dev hardhat
初始化为hardhat项目,选择Create an empty hardhat.config.js
,然后回车,hardhat将会创建一个新的hardhat.config.js
npx hardhat init
$ npx hardhat init
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.18.3
? What do you want to do? …
Create a JavaScript project
Create a TypeScript project
▸ Create an empty hardhat.config.js
Quit
编写智能合约
在项目根目录下创建contracts
的新目录
mkdir contracts
此时目录结构为:
$ tree -L 1
.
├── contracts
├── hardhat.config.js
├── node_modules
├── package-lock.json
└── package.json
3 directories, 3 files
在contracts
中创建一个Token.sol
文件用于编写Solidity合约,如下:
vim contracts/Token.sol
// SPDX-License-Identifier: GPL-3.0
// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity ^0.8.9;
// This is the main building block for smart contracts.
contract Token {
// Some string type variables to identify the token.
// The `public` modifier makes a variable readable from outside the contract.
string public name = "My Hardhat Token";
string public symbol = "MBT";
// 固定发行量,保存在一个无符号整型里
uint256 public totalSupply = 1000000;
// An address type variable is used to store ethereum accounts.
address public owner;
// A mapping is a key/value map. Here we store each account balance.
mapping(address => uint256) balances;
/**
* 合约构造函数
*
* The `constructor` is executed only once when the contract is created.
*/
constructor() {
// The totalSupply is assigned to transaction sender, which is the account
// that is deploying the contract.
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
/**
* 代币转账.
*
* The `external` modifier makes a function *only* callable from outside
* the contract.
*/
function transfer(address to, uint256 amount) external {
// Check if the transaction sender has enough tokens.
// If `require`'s first argument evaluates to `false` then the
// transaction will revert.
require(balances[msg.sender] >= amount, "Not enough tokens");
// Transfer the amount.
balances[msg.sender] -= amount;
balances[to] += amount;
}
/**
* 返回账号的代币余额,只读函数。
*
* The `view` modifier indicates that it doesn't modify the contract's
* state, which allows us to call it without executing a transaction.
*/
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
}
此时的目录结构
# -I: 排除指定目录,node_modules中内容太多
$ tree -I 'node_modules'
.
├── contracts
│ └── Token.sol
├── hardhat.config.js
├── package-lock.json
└── package.json
编译智能合约
在终端执行以下命令进行编译:
$ npx hardhat compile
Compiled 1 Solidity file successfully (evm target: paris).
此时的目录结构:
# -I: 排除指定目录,node_modules中内容太多
$ tree -I 'node_modules'
.
├── artifacts
│ ├── build-info
│ │ └── 90260d8de0becfb3d43b8782741d821b.json
│ └── contracts
│ └── Token.sol
│ ├── Token.dbg.json
│ └── Token.json
├── cache
│ └── solidity-files-cache.json
├── contracts
│ └── Token.sol
├── hardhat.config.js
├── package-lock.json
└── package.json
artifacts/contracts/Token.sol/Token.json
,内部包含有合约bytecode
和abi
信息
Hardhat 测试
创建测试目录,在项目根目录下创建test
目录
mkdir test
此时目录结构为:
$ tree -L 1
.
├── artifacts
├── cache
├── contracts
├── hardhat.config.js
├── node_modules
├── package-lock.json
├── package.json
└── test
6 directories, 3 files
简单测试用例
在test
目录下创建Token.js
用于编写与Token.sol
合约相关的测试代码,代码如下:
const { expect } = require("chai");
describe("Token contract", function() {
it("Deployment should assign the total supply of tokens to the owner", async function() {
const [owner] = await ethers.getSigners();
const Token = await ethers.getContractFactory("Token");
const hardhatToken = await Token.deploy();
const ownerBalance = await hardhatToken.balanceOf(owner.address);
expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
});
});
部署合约到Hardhat Network
refs
- Hardhat模板工程
- Hardhat 文档
- Hardhat Toolbox's 文档
- Ethers.js 文档 及 ethers.js文档中文版
- Waffle 文档
- Mocha 文档
- Chai 文档
- Solidity 教程 全面的 Solidity 合约教程。
- Alchemy 合约教程 也可以学习如何使用Metamask和Solidity,以及像Alchemy提供的RPC端点。