JavaScript 不可用。

我们检测到浏览器禁用了 JavaScript。请启用 JavaScript 或改用支持的浏览器来继续访问

Hardhat 项目测试的常见操作

作者:Anban Chu

发表日期:2023年12月27日

所属目录:合约开发

标签:
  • Hardhat: 基于 2.19 版本的
    • contract.target 是合约地址。
  • ethers: ^6.4.0
    • ethers.parseEther('1')

console

import "hardhat/console.sol";
console.log(amount);

test

import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
// import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'
import { expect } from "chai";
import { ethers } from "hardhat";
import { BigNumber } from "ethers";

获取地址

const address = await ethers.getSigners(); // address 是一个地址集合

// 地址展开
const [owner, user1, user2, user3, user4, user5, user6, user7, user8, user9, user10] = await ethers.getSigners();

如果需要多账号多金额

		hardhat: {
			allowUnlimitedContractSize: true,
			chainId: 22,
			accounts: {
				count: 100,
				accountsBalance: "88880000000000000000000000",
			},
		},

部署合约

const Lock = await ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });

时间穿梭

await time.increaseTo(unlockTime); // 穿梭时间
await time.advanceBlockTo(20); // 穿梭区块

异常判断

// 基本
expect(await lock.owner()).to.equal(owner.address); // 相等
expect(await lock.xxx()).to.be.not.equal(10); // 不相等
expect(await lock.xxx()).to.be.above(5); // 大于
expect(await lock.xxx()).to.be.least(5); // 大于等于
expect(await lock.xxx()).to.be.below(20); // 小于
expect(await lock.xxx()).to.be.most(20); // 小于等于
 




// reverted
await expect(contract.call()).to.be.reverted; // reverted
await expect(lock.withdraw()).not.to.be.reverted; // not reverted

// reverted 预期错误信息
await expect(contract.call()).to.be.revertedWith("Some revert message");
await expect(contract.call()).not.to.be.revertedWith("Another revert message");
// ------> owner 普通合约错误
await expect(xxx.connect(user4).setClaimable(false)).to.be.revertedWith('Ownable: caller is not the owner')

// 自定义错误
await expect(contract.call()).to.be.revertedWithCustomError(contract, "SomeCustomError");
await expect(contract.call()).to.be.revertedWithCustomError(contract, "SomeCustomError").withArgs(anyValue, "some error data string");
// ------> owner 可升级合约错误
await expect(xxx.connect(user4).setClaimable(false)).to.be.revertedWithCustomError(xxx, "OwnableUnauthorizedAccount").withArgs(user4.address);


// 事件触发
await expect(lock.withdraw()).to.emit(lock, "Withdrawal").withArgs(lockedAmount, anyValue);

// ETH余额变化
await expect(lock.withdraw()).to.changeEtherBalances([owner, lock], [lockedAmount, -lockedAmount]);
await expect(() => sender.sendTransaction({ to: someAddress, value: 200 })).to.changeEtherBalance(sender, "-200");
await expect(token.transfer(account, 1)).to.changeTokenBalance(token, account, 1);
// 多个地址同时检查
await expect(() => sender.sendTransaction({ to: receiver, value: 200 })).to.changeEtherBalances([sender, receiver], [-200, 200]);
await expect(token.transferFrom(sender, receiver, 1)).to.changeTokenBalances(token, [sender, receiver], [-1, 1]);

一些库的接口实现判断

it('supportsInterface', async function () {
    const { owner, admin, dev, treasury, user1, user2, user3, xxx } = await loadFixture(deployFixture)
    // ERC165               0x01ffc9a7
    // ERC721               0x80ac58cd
    // ERC721Metadata       0x5b5e139f
    // ERC721TokenReceiver  0x150b7a02
    // ERC721Enumerable     0x780e9d63
    // AccessControl        0x7965db0b
    expect(await xxx.supportsInterface('0x01ffc9a7')).to.equal(true);
    expect(await xxx.supportsInterface('0x80ac58cd')).to.equal(true);
    expect(await xxx.supportsInterface('0x5b5e139f')).to.equal(true);
    expect(await xxx.supportsInterface('0x150b7a02')).to.equal(false);
    expect(await xxx.supportsInterface('0x780e9d63')).to.equal(false);
    expect(await xxx.supportsInterface('0x7965db0b')).to.equal(false);
})

fallback 测试

it('🥷 should invoke the fallback()', async function () {
    const { deployer, owner, user4, xxx } = await loadFixture(deployFixture);
    await expect(user4.sendTransaction({
        to: xxx.target,
        data: "0xdf"
    }))
        .to.emit(xxx, "UnknownError").withArgs(user4.address, "0xdf");
})

Debug

ether.js

转账给其他地址

// 转账给其他地址
const [owner, user1, user2, user3, user4, user5, user6, user7, user8, user9, user10] = await ethers.getSigners();
await user10.sendTransaction({
	to: user1.address,
	value: ethers.utils.parseEther("1.0"), // Sends exactly 1.0 ether
});

const balance = await ethers.provider.getBalance(user1.address);
expect(balance).to.equal(ethers.parseEther('1'))

测试 library

使用 waffle 来进行。

https://stackoverflow.com/questions/72936183/how-to-directly-test-a-solidity-library-with-hardhat-chai

更多参考资料

相关的命令

Command Line

  • install :
    • npm i
  • create .env file in project root path
    • mirror .env.example
  • compile :
    • npm run compile
    • if got Error HH12: run command npm install --save-dev hardhat
  • test :
    • npm run test
  • coverage :
    • npm run coverage
  • view methods gas :
    • npm run gas
  • deploy on hardhat temp network
    • npm run d
  • deploy on localhost network
    • Terminal 1: npm run node
    • Terminal 2: npm run d:l
  • deploy on blockchain network
    • ✅ Product: npm run d:fbchain

All scripts is in package.json file.

Open in remixd web

  1. npm install -g @remix-project/remixd
  2. remixd / npm run remixd

常见的命令

"scripts": {
  "compile": "npx hardhat compile && node batch/abi.ts",
  "docs": "npx hardhat dodoc",
  "node": "npx hardhat node",
  "test": "npx hardhat test",
  "coverage": "npx hardhat coverage && npx http-server ./coverage/ -o",
  "gas": "REPORT_GAS=true npx hardhat test",
  "abi": "npx hardhat export-abi",
  "d": "npx hardhat run scripts/deploy.ts",
  "d:l": "npx hardhat run --network localhost scripts/deploy.js",
  "d:test": "npx hardhat run scripts/deploy.ts --network bsc_test",
  "d:bsc": "npx hardhat run scripts/deploy.ts --network bsc",
  "up": "npx hardhat run scripts/upgrade.ts --network bsc_test",
  "v:test": "npx hardhat verify --network bsc_test <CONTRACT_ADDRESS>",
  "v:bsc": "npx hardhat verify --network bsc <CONTRACT_ADDRESS>",
  "remixd": "open http://remix.ethereum.org/ && remixd -s  ./  --remix-ide http://remix.ethereum.org/",
  "lint": "solhint 'contracts/*.sol'",
  "lint:fix": "solhint 'contracts/**/*.sol' --fix",
  "format": "prettier --write .",
},

参考





以上就是本篇文章的全部内容了,希望对你有帮助。

>> 本站不提供评论服务,技术交流请在 Twitter 上找我 @anbang_account