I have a basic ERC-20 Token defined as

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor() ERC20("Token", "TOKEN") {}

    function mint(address account, uint256 amount) public {
        _mint(account, amount);

I have another contract Item that has a method I want to cost 1 Token, basing answer off https://ethereum.stackexchange.com/a/78911/30804

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Item {
    IERC20 private token;

    constructor(address tokenAddress) {
        token = IERC20(tokenAddress);

    function myMethod() public {
        bool success = token.transferFrom(msg.sender, address(this), 1 ether); // also tried just 1
        require(success, "Insufficient Funds: Requires 1 Token");
        // do things

I'm running this inside a Hardhat test

  const TokenFactory = await ethers.getContractFactory("Token");
  Token = await Token.deploy();
  await Token.mint(owner.address, ethers.utils.parseUnits("1", 18));
  await Token.approve(owner.address, ethers.utils.parseUnits("1", 18));

  const ItemFactory = await ethers.getContractFactory("Item");
  Item = await ItemFactory.deploy(Token.address);
  await Item.myMethod(); // this is the line that errors

Everything runs and I can see debug code from the solidity contracts, but I keep getting an error that

reverted with reason string 'ERC20: insufficient allowance'

that I traced back to the openzeppelin internal function _spendAllowance

After some debugging I thought that the culprit was because I needed to approve, so I added a call to approve but I'm still getting the same error

I'm assuming my issue is something basic can anyone see what it might be? Thanks in advance.

1 Answer 1

 await Token.approve(owner.address, ethers.utils.parseUnits("1", 18));

In this line you are sending the owner address as the spender, you must pass the actual address of the recipient, and make sure the call of Token.approve is being performed by the owner.

  • 1
    Yes thanks! I changed my approval line to await Token.approve(Item.address, ethers.utils.parseUnits("1", 18)); and it's working great now Commented Jun 15, 2022 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.