I'm using Hardhat framewrok and doing some testing with an erc20
contract:
await expect(
ERC20Contract.transferFrom(ERC20Contract.address, deployer, amount)
).to.be.revertedWith("ERC20: insufficient allowance");
I'm expecting the contract to revert with an error of : ERC20: insufficient allowance
Here is the require statement from the contract:
require(currentAllowance >= amount, "ERC20: insufficient allowance");
and this is the error I'm getting:
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)
in the error message I can see ERC20: insufficient allowance
but the expect
function is not getting it and failing the test.
Here is the contract:
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);
}
}
Deploy:
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"];
Test:
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");
});
});
Best Answer
So after almost a day of debugging it turns out that I need another plugin to use
revertedWith()
I need to installnpm install --save-dev @nomiclabs/hardhat-waffle 'ethereum-waffle@^3.0.0' @nomiclabs/hardhat-ethers 'ethers@^5.0.0'
and import it in the config file, otherwise I need to userejectedWith("ERC20: insufficient allowance")
.if anyone can explain this further it would be better because still I don't whats the difference between
revertedWith
andrejectedWith
and why we need to installhardhat-waffle
to be able to userevertedWith
.more info about
hardhat-waffle
in this page: https://hardhat.org/hardhat-runner/plugins/nomiclabs-hardhat-waffle