'Paying with ERC20 token

I want to build an NFT that I can paid with an ERC-20 token to mint it. I'm using currently the Mumbai testnet on polygon, and I'm using the Dummy ERC20 token to test it out.

This is currently my constructor:

ERC20 token;

constructor() ERC721("Token", "TKN") {
  token = ERC20(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1);
}

And this is my mint function:

  function mint() public returns (uint256) {
    uint256 tokenId = _tokenIds.current();
    require(tokenId <= MAX_TOKEN_ID);

    token.approve(address(this), NFT_PRICE);
    token.transfer(address(this), NFT_PRICE);

    _mint(msg.sender, tokenId);
    _setTokenURI(tokenId, TOKEN_URI);

    _tokenIds.increment();
    return tokenId;
  }

If I remove those 2 lines the code works fine, it mints the NFT:

token.approve(address(this), NFT_PRICE);
token.transfer(address(this), NFT_PRICE);

But as soon as I add it, the code breaks, it gives me the following gas estimation error:

The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": 3, "message": "execution reverted: ERC20: transfer amount exceeds balance", "data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000" }

As a troubleshooting step I've also added this inside my mint function to make sure I'm calling from my own wallet:

sender = msg.sender;

And created this function:

function tokenBalance(address addr) public view returns (uint256) {
   return token.balanceOf(addr);
}

And if I grab the token balance of the sender address it gives me the value:

0: uint256: 2000000000000000000


Solution 1:[1]

It's because the logic is wrong. That approve function you call inside your mint function is useless: the spender needs to call the approve function from the the contract of your dummy ERC20.

And then you can call the transferFrom(msg.sender, address(this), NFT_PRICE) from your mint function.

Sources

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

Source: Stack Overflow

Solution Source
Solution 1 Niccolò Fant