'Transaction reverted: function selector was not recognized and there's no fallback function

I am interacting with my own smart contract. It's a very simple one.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ERC20 {
  string public name;
  string public symbol;
  uint8 public decimal = 18;
  uint256 public totalSupply;
  address internal immutable _owner;
  mapping(address => uint256) internal _accounts;
  mapping(address => mapping(address => uint256)) internal _allowed;

  constructor(
    string memory name_,
    string memory symbol_,
    uint256 totalSupply_
  ) {
    _owner = msg.sender;
    name = name_;
    symbol = symbol_;
    totalSupply = totalSupply_;
    _accounts[msg.sender] = totalSupply;
  }

  // Events
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);

  // Errors
  /// @notice Insufficient Funds.
  error InsufficientFunds(
    address account,
    uint256 currentFunds,
    uint256 requestedFunds
  );

  /// @notice Invalid Address.
  error InvalidAddress(address account);

  /// @notice Unauthorized.
  error Unauthorized(address account);

  /// @notice Not Allowed.
  error NotAllowed(address owner, address spender, uint256 amount);

  // Modifiers
  modifier sufficientFunds(address account, uint256 amount) {
    if (_accounts[account] < amount)
      revert InsufficientFunds(account, _accounts[account], amount);
    _;
  }

  modifier validAddress(address account) {
    if (account == address(0)) revert InvalidAddress(account);
    _;
  }

  modifier onlyOwner() {
    if (msg.sender != _owner) revert Unauthorized(msg.sender);
    _;
  }

  modifier allowed(address account, uint256 amount) {
    if (_allowed[account][msg.sender] < amount)
      revert NotAllowed(account, msg.sender, amount);
    _;
  }

  // Functions
  function balanceOf(address account_) external view returns (uint256 balance) {
    balance = _accounts[account_];
  }

  function allowance(address owner_, address spender_)
    external
    view
    returns (uint256 amount)
  {
    amount = _allowed[owner_][spender_];
  }

  function transfer(address to_, uint256 amount_)
    external
    validAddress(to_)
    sufficientFunds(msg.sender, amount_)
    returns (bool result)
  {
    _accounts[msg.sender] -= amount_;
    _accounts[to_] += amount_;

    emit Transfer(msg.sender, to_, amount_);
    result = true;
  }

  function approve(address spender_, uint256 amount_)
    external
    validAddress(spender_)
    sufficientFunds(msg.sender, amount_)
    returns (bool result)
  {
    _allowed[msg.sender][spender_] += amount_;

    emit Approval(msg.sender, spender_, amount_);
    result = true;
  }

  function transferFrom(
    address from_,
    address to_,
    uint256 amount_
  )
    external
    validAddress(from_)
    validAddress(to_)
    allowed(from_, amount_)
    sufficientFunds(from_, amount_)
    returns (bool result)
  {
    _allowed[from_][msg.sender] -= amount_;
    _accounts[from_] -= amount_;
    _accounts[to_] += amount_;

    emit Transfer(from_, to_, amount_);
    result = true;
  }
}

This contract is covered by tests and working fine. Deploying it locally however is causing the approve method to revert with this error

Error: Transaction reverted: function selector was not recognized and there's
no fallback function at ERC20.<unrecognized-selector> 

Calling decimal(), symbol() or transfer() works perfectly. It's just the approve() method that is causing this problem and I cannot figure out the reason. I am using Hardhat and Ethers by the way.

deploy.ts (working)

const ERC20 = (await ethers.getContractFactory(
    'ERC20'
  )) as ERC20__factory;

const claimableTokens = [
    await ERC20.deploy('Token 1', 'T1', toWei(1000000)),
    await ERC20.deploy('Token 2', 'T2', toWei(10000)),
    await ERC20.deploy('Token 3', 'T3', toWei(100)),
  ];

await Promise.all(claimableTokens.map((token) => token.deployed()));

await (
  await claimableTokens[0].approve(witSwap.address, toWei(500000))
).wait();

blockchain.ts (not working)

const token1Contract = 
  new ethers.Contract(
    address,
    ERC20JSON.abi,
    this._provider
  ) as ERC20;

token1Contract
  .connect(this._signer)
  .approve(contractAddress, token1Amount)

logging token1Contract from blockchain.ts shows the desired functions.

Any help is much appreciated!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source