hardhat提供了很多我们在使用ethers.js时很难实现的工具或者快捷的方法
yarn hardhat
根据提示生成一个简单的框架模版 例如这样:
{ "name": "hardhat-simple-storage-fcc", "author": "maochaoying", "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.4", "@nomiclabs/hardhat-etherscan": "^3.0.0", "@nomiclabs/hardhat-waffle": "^2.0.2", "chai": "^4.3.4", "ethereum-waffle": "^3.4.0", "ethers": "^5.5.3", "hardhat": "^2.8.3", "hardhat-gas-reporter": "^1.0.7", "solidity-coverage": "^0.7.18" }, "dependencies": { "dotenv": "^14.2.0", "prettier-plugin-solidity": "^1.0.0-beta.19" }, "scripts": { "lint": "yarn prettier --check .", "lint:fix": "yarn prettier --write ." } }
hardhat提供了一个查看当前我们编写的测试代码的功能覆盖率的插件,叫做solidity-coverage,专门用于可靠性测试的代码覆盖率。
gas费是我们每一次与区块链交互的时候产生的一笔费用,每次我们读取数据,运算数据,修改数据的时候,都会产生一定数量的gas。
gas费是我们与区块链通信的过程中提交的费用,,我们通过一定的语法技巧能节约很多的gas,给用户操作节省gas费,一个优秀的项目应该避免大量gas的消耗。
hardhat-gas-reporter是hardhat的一个插件,专门用于查看每个单元测试所消耗的gas费用。
为了防止privete_key暴露在代码里,我们需要将一些密钥抽离在.env
文件中,并在.gitignore
中排除它,而后在使用处添加npm包dotenv
进行引入。
例如:
PRIVATE_KEY=234523425asdfasdfa GOERLI_RPC_URL=http://0.0.0.0:8545 COINMARKETCAP_API_KEY=asdfasdfasdfasdfasdfasdfasdf ETHERSCAN_API_KEY=asdfasdfasdfs
// SPDX-License-Identifier: MIT pragma solidity 0.8.8; // pragma solidity ^0.8.0; // pragma solidity >=0.8.0 <0.9.0; contract SimpleStorage { uint256 favoriteNumber; struct People { uint256 favoriteNumber; string name; } // uint256[] public anArray; People[] public people; mapping(string => uint256) public nameToFavoriteNumber; function store(uint256 _favoriteNumber) public { favoriteNumber = _favoriteNumber; } function retrieve() public view returns (uint256) { return favoriteNumber; } function addPerson(string memory _name, uint256 _favoriteNumber) public { people.push(People(_favoriteNumber, _name)); nameToFavoriteNumber[_name] = _favoriteNumber; } }
hardhat中内置了ethers对象
(ethers.js库旨在为以太坊区块链及其生态系统提供一个小而完整的 JavaScript API 库 )、network对象
(包括网络的一些常用参数)、run函数(执行hardhat的任务)。
// imports const { ethers, run, network } = require("hardhat") // async main async function main() { const SimpleStorageFactory = await ethers.getContractFactory("SimpleStorage") console.log("Deploying contract...") const simpleStorage = await SimpleStorageFactory.deploy() await simpleStorage.deployed() console.log(`Deployed contract to: ${simpleStorage.address}`) // what happens when we deploy to our hardhat network? if (network.config.chainId === 5 && process.env.ETHERSCAN_API_KEY) { console.log("Waiting for block confirmations...") await simpleStorage.deployTransaction.wait(6) await verify(simpleStorage.address, []) } const currentValue = await simpleStorage.retrieve() console.log(`Current Value is: ${currentValue}`) // Update the current value const transactionResponse = await simpleStorage.store(7) await transactionResponse.wait(1) const updatedValue = await simpleStorage.retrieve() console.log(`Updated Value is: ${updatedValue}`) } // async function verify(contractAddress, args) { const verify = async (contractAddress, args) => { console.log("Verifying contract...") try { await run("verify:verify", { address: contractAddress, constructorArguments: args, }) } catch (e) { if (e.message.toLowerCase().includes("already verified")) { console.log("Already Verified!") } else { console.log(e) } } } // main main() .then(() => process.exit(0)) .catch((error) => { console.error(error) process.exit(1) })
setAction
设置执行后的具体行为const { task } = require("hardhat/config") task("block-number", "Prints the current block number").setAction( // const blockTask = async function() => {} // async function blockTask() {} async (taskArgs, hre) => { const blockNumber = await hre.ethers.provider.getBlockNumber() console.log(`Current block number: ${blockNumber}`) } ) module.exports = {}
进行全局配置和引入一些插件
require("@nomiclabs/hardhat-waffle") require("hardhat-gas-reporter") require("./tasks/block-number") require("@nomiclabs/hardhat-etherscan") require("dotenv").config() require("solidity-coverage") // You need to export an object to set up your config // Go to https://hardhat.org/config/ to learn more /** * @type import('hardhat/config').HardhatUserConfig */ const COINMARKETCAP_API_KEY = process.env.COINMARKETCAP_API_KEY || "" const GOERLI_RPC_URL = process.env.GOERLI_RPC_URL || "https://eth-goerli.alchemyapi.io/v2/your-api-key" const PRIVATE_KEY = process.env.PRIVATE_KEY || "0x11ee3108a03081fe260ecdc106554d09d9d1209bcafd46942b10e02943effc4a" const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || "" module.exports = { defaultNetwork: "hardhat", networks: { hardhat: {}, goerli: { url: GOERLI_RPC_URL, accounts: [PRIVATE_KEY], chainId: 5, }, localhost: { url: "http://localhost:8545", chainId: 31337, }, }, solidity: "0.8.8", etherscan: { apiKey: ETHERSCAN_API_KEY, }, gasReporter: { enabled: true, currency: "USD", outputFile: "gas-report.txt", noColors: true, coinmarketcap: COINMARKETCAP_API_KEY, }, }
const { ethers } = require("hardhat") const { expect, assert } = require("chai") // describe("SimpleStorage", () => {}) describe("SimpleStorage", function () { // let simpleStorageFactory // let simpleStorage let simpleStorageFactory, simpleStorage beforeEach(async function () { simpleStorageFactory = await ethers.getContractFactory("SimpleStorage") simpleStorage = await simpleStorageFactory.deploy() }) it("Should start with a favorite number of 0", async function () { const currentValue = await simpleStorage.retrieve() const expectedValue = "0" // assert // expect assert.equal(currentValue.toString(), expectedValue) // expect(currentValue.toString()).to.equal(expectedValue) }) it("Should update when we call store", async function () { const expectedValue = "7" const transactionResponse = await simpleStorage.store(expectedValue) await transactionResponse.wait(1) const currentValue = await simpleStorage.retrieve() assert.equal(currentValue.toString(), expectedValue) }) // Extra - this is not in the video it("Should work correctly with the people struct and array", async function () { const expectedPersonName = "Patrick" const expectedFavoriteNumber = "16" const transactionResponse = await simpleStorage.addPerson( expectedPersonName, expectedFavoriteNumber ) await transactionResponse.wait(1) const { favoriteNumber, name } = await simpleStorage.people(0) // We could also do it like this // const person = await simpleStorage.people(0) // const favNumber = person.favoriteNumber // const pName = person.name assert.equal(name, expectedPersonName) assert.equal(favoriteNumber, expectedFavoriteNumber) }) })
本文作者:前端小毛
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!