跳到主要内容

Hardhat

HardhatNodejs 环境下以太坊智能合约开发框架。提供了一套完整的工具链,可以更轻松地在以太坊网络上编译、测试和部署智能合约。借助 Hardhat,开发人员使用以太坊最流行的编程语言 Solidity 编写智能合约,并利用自动合约测试、合约调试等高级功能。同时 Hardhat 还提供了一系列插件,可进一步扩展其功能。这些插件涵盖了广泛的用例,从安全和审计到工具和集成。

安装

  • 安装 Node.js: 直接从 Nodejs 官网 下载安装即可

  • 创建项目: 创建项目文件夹, 进入项目文件夹后执行命令

    npm init
    npm i hardhat -d
  • 初始化项目: 执行命令 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.17.4 👷‍

    ? What do you want to do? …
    ❯ Create a JavaScript project
    Create a TypeScript project
    Create an empty hardhat.config.js
    Quit

初始化完成后会生成 hardhat.config.jshardhat.config.ts, 根据你选择的语言不同, 会生成不同的文件名后缀,该文件是 Hardhat 的配置文件。

配置

import { HardhatUserConfig } from 'hardhat/config'
import '@nomicfoundation/hardhat-toolbox'
import '@nomicfoundation/hardhat-verify'

import * as dotenv from 'dotenv'
dotenv.config()

const config: HardhatUserConfig = {
solidity: {
version: '0.8.19' // 使用 solidity 编译器版本
},
networks: {
baseGoerli: {
chainId: 84531,
url: process.env.ALCHEMY_BASE_GOERLI_URL, // rpc url
accounts: [process.env.SECRET_KEY] // 私钥数组
}
},
etherscan: {
apiKey: process.env.ETHERSCAN_APIKEY // etherscan api key
}
}

export default config

配置文件主要包括以下字段

  • solidity: 使用 solidity 编译器配置
  • networks: 网络配置, 可配置多个
  • etherscan: 上传源码时使用
注意

配置文件中包含一些敏感信息, 如果你是使用 git 作代码管理,会很容易暴露这些数据。建议使用 dotenv

安装 dotenv

npm i dotenv -d

项目根目录下创建 .env 文件, 并将其加入到 .gitignore, 配置内容

# 私钥
SECRET_KEY=""
# api key
ETHERSCAN_APIKEY=""
# rpc
ALCHEMY_BASE_GOERLI_URL=""

配置文件中加载

import * as dotenv from 'dotenv'
dotenv.config()

dotenv.config() 会读取 .env 文件的内容,并加载到 process.env

使用

contracts 完成智能的代码编写后

编译

下面命令用于编译智能合约

npx hardhat compile

部署

部署需要通过脚本完成, 在 scriptsdeploy.ts

import { ethers } from 'hardhat'

async function main() {
const currentTimestampInSeconds = Math.round(Date.now() / 1000)
const unlockTime = currentTimestampInSeconds + 60
const lockedAmount = ethers.parseEther('0.001')

// 部署合约, (合约名, [合约构造函数参数], 携带的资金)
const lock = await ethers.deployContract('Lock', [unlockTime], {
value: lockedAmount
})
await lock.waitForDeployment()

console.log(
`Lock with ${ethers.formatEther(
lockedAmount
)}ETH and unlock timestamp ${unlockTime} deployed to ${lock.target}`
)
}

// 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
})

写好部署脚本后,执行下面的命令用来部署

npx hardhat run script/deploy.ts --network baseGoerli

部署的网络来自于配置文件

测试

测试智能合约的脚本写在 test 文件夹

import { expect } from 'chai'
import hre from 'hardhat'
import { time } from '@nomicfoundation/hardhat-toolbox/network-helpers'

describe('Lock', function () {
it('Should set the right unlockTime', async function () {
const lockedAmount = 1_000_000_000
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS

// deploy a lock contract where funds can be withdrawn
// one year in the future
const lock = await ethers.deployContract('Lock', [unlockTime], {
value: lockedAmount
})

// assert that the value is correct
expect(await lock.unlockTime()).to.equal(unlockTime)
})
})

运行单元测试

npx hardhat test

verify

verify 的过程就是上传源码到 etherscan , 需要在配置文件中配置 etherscan.apiKey,值来自于 etherscan

首先进入 etherscan 并注册, 在 apikey 页面 添加后将值回填到该字段即可

接着执行下面命令

npx hardhat verify --network baseGoerli address params
  • address: 合约地址,在执行部署脚本后得到
  • params: 合约的构造函数参数, 复杂参数见 hardhat-verify