Hardhat
安全帽期望沒有得到恢復原因
我正在使用 Hardhat 框架並通過
erc20
契約進行一些測試:await expect( ERC20Contract.transferFrom(ERC20Contract.address, deployer, amount) ).to.be.revertedWith("ERC20: insufficient allowance");
我預計契約會因以下錯誤而恢復:
ERC20: insufficient allowance
這是契約中的要求聲明:
require(currentAllowance >= amount, "ERC20: insufficient allowance");
這是我得到的錯誤:
Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (error={"name":"ProviderError","_stack":"ProviderError: HttpProviderError\n at HttpProvider.request (/home/kadiemq/hh-tut/erc20-tut/node_modules/hardhat/src/internal/core/providers/http.ts:78:19)\n at LocalAccountsProvider.request (/home/kadiemq/hh-tut/erc20-tut/node_modules/hardhat/src/internal/core/providers/accounts.ts:187:34)\n at processTicksAndRejections (node:internal/process/task_queues:96:5)\n at async EthersProviderWrapper.send (/home/kadiemq/hh-tut/erc20-tut/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)","code":-32000,"_isProviderError":true,"data":{"stack":"RuntimeError: VM Exception while processing transaction: revert ERC20: insufficient allowance\n at Function.RuntimeError.fromResults (/tmp/.mount_ganachAQrIFW/resources/static/node/node_modules/ganache-core/lib/utils/runtimeerror.js:94:13)\n at module.exports (/tmp/.mount_ganachAQrIFW/resources/static/node/node_modules/ganache-core/lib/utils/gas/guestimation.js:142:32)","name":"RuntimeError"}}, tx={"data":"0x23b872dd000000000000000000000000624daf7e06c04e0ab541323b3d3e95b629745a6000000000000000000000000033757dfeda24de8dc2b46d348a035ad60bbc3a3f0000000000000000000000000000000000000000000000000de0b6b3a7640000","to":{},"from":"0x2c93fc47DC6aaF30CD5a6C47F59bD898842B0190","gasPrice":{"type":"BigNumber","hex":"0x04a817c800"},"type":0,"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.7.0)
在錯誤消息中我可以看到
ERC20: insufficient allowance
,但該expect
功能沒有得到它並且測試失敗。這是契約:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract OurToken is ERC20 { constructor(uint256 initialSupply) ERC20("OurToken", "OT") { _mint(address(this), initialSupply); _approve(address(this), msg.sender, initialSupply); } }
部署:
import { DeployFunction } from "hardhat-deploy/dist/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { developmentChains, INITIAL_SUPPLY, networkConfig, } from "../helper-hardhat-config"; const DeployToken: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { getNamedAccounts, deployments, network } = hre; const { deploy, log } = deployments; const { deployer } = await getNamedAccounts(); const chainId = network.config.chainId!; const args = [INITIAL_SUPPLY]; const OurToken = await deploy("OurToken", { from: deployer, args: args, log: true, waitConfirmations: networkConfig[network.name].blockConfirmations || 1, }); }; export default DeployToken; DeployToken.tags = ["all", "token"];
測試:
import { deployments, ethers, getNamedAccounts } from "hardhat"; import { ERC20 } from "../typechain-types"; import { assert, expect } from "chai"; describe("Testing", async () => { let deployer: string; let second: string; let ERC20Contract: ERC20; beforeEach(async () => { deployer = (await getNamedAccounts()).deployer; second = (await getNamedAccounts()).second; await deployments.fixture(["all"]); }); it("testing with deployer", async () => { ERC20Contract = await ethers.getContract("OurToken", deployer); const amount = ethers.utils.parseEther("1"); const previousBalance = await ERC20Contract.balanceOf(deployer); const tx = await ERC20Contract.transferFrom( ERC20Contract.address, deployer, amount ); tx.wait(1); const newBalance = await ERC20Contract.balanceOf(deployer); assert.equal( previousBalance.add(amount).toString(), newBalance.toString() ); }); it("testing with second", async () => { ERC20Contract = ERC20Contract.connect(second); const amount = ethers.utils.parseEther("1"); await expect( ERC20Contract.transferFrom(ERC20Contract.address, deployer, amount) ).to.be.revertedWith("ERC20: insufficient allowance"); }); });
revertedWith
是 waffle 庫中的一個 chai 匹配器,用於斷言還原的錯誤數據匹配或不匹配特定字元串。
rejectedWith
是一個 chai 外掛,用於擴展 chai 以斷言有關承諾的事實。
hardhat-waffle
是一個用於與 Waffle 集成的安全帽外掛,因此如果您想使用revertedWith
Waffle 的 chai matcher,則需要在安全帽中安裝此外掛。您也可以安裝@nomicfoundation/hardhat-chai-matchers
以revertedWith
在安全帽中使用。看:
https://ethereum-waffle.readthedocs.io/en/latest/matchers.html
您是否已批准
ERC20Contract.address
轉讓?您應確保已批准將指定金額轉入的契約deployer
請提供整個程式碼或至少提供它處理的函式和狀態變數,以便我可以幫助您。
編輯:在你發布了整個程式碼之後,我看到它在 TS 中,這不是我的權力。但是我為 JS 執行了等效的程式碼,它執行良好:
const { ethers } = require("hardhat"); const { assert, expect } = require("chai"); let ERC20Contract; let contract; describe("Testing", async () => { beforeEach(async () => { [owner, second] = await ethers.getSigners(); ERC20Contract = await ethers.getContractFactory("OurToken"); //getting the contract factory contract = await ERC20Contract.deploy(500); //providing arguments to the construcotr and deploying it await contract.deployed(); let balance = await contract.balanceOf(contract.address); console.log(balance); }); it("testing with second", async () => { const amount = 300; await expect( contract .connect(second) .transferFrom(contract.address, second.address, amount) ).to.be.revertedWith("ERC20: insufficient allowance"); }); });