0

Getting ERC20: insufficient allowance even I'm calling approve function before calling transferFrom function in getRewards function, don't know what I'm missing in it.

Cafe Contract:

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

// Uncomment this line to use console.log
// import "hardhat/console.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Cafe is Ownable {
    address public cafeToken;

    function setCafeToken(address _cafeToken) public onlyOwner {
        cafeToken = _cafeToken;
    }

    //send token to other receipent
    function sendToken(
        address _receiverAddress,
        uint _tokenAmount
    ) public onlyOwner {
        require(_tokenAmount > 0, "token should be more than 0");

        IERC20(cafeToken).transfer(_receiverAddress, _tokenAmount);
    }

    function getRewards() public {
        require(
            IERC20(cafeToken).balanceOf(msg.sender) >= 10000000000000000000,
            "you should have more then 10 tokens..."
        );
        IERC20(cafeToken).approve(msg.sender, 10000000000000000000);
        IERC20(cafeToken).transferFrom(
            msg.sender,
            address(this),
            10000000000000000000
        );
    }   
}

Cafe Token Contract:

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

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

contract CAFToken is ERC20 {
    constructor(
        uint256 initialSupply,
        address cafeAddress
    ) ERC20("Cafe", "CAF") {
        _mint(cafeAddress, initialSupply); // mint intial supply to cafe contract
    }
}

first I'm deploying Cafe Contract and then cafeToken contract with deployed address of cafe contract.

1 Answer 1

1

The approve() call inside the getRewards() function approves 10000000000000000000 tokens from Cafe (owner) to be spendable by msg.sender (spender).

However, you actually want that the msg.sender approves the number of tokens to be spent by the Cafe contract, i.e. the msg.sender is the owner of tokens and the Cafe contract the spender.

This is only possible (leaving permit functionality out of scope) via the msg.sender making a transaction beforehand calling:

IERC20(cafeToken).approve(address(Cafe), 10000000000000000000)

Inside the getRewards() function, you could add a check ensuring the allowance for Cafe is sufficient, e.g. by using something like:

require(IERC20(cafeToken).allowance(msg.sender, address(this)) >= 10000000000000000000, "Insufficient allowance");

Note that in the allowance() call, msg.sender is the owner of the token, and address(this) is the spender.

3
  • Thank you @merkleplant, It's really very helpful to me an Issue has been fixed Mar 30, 2023 at 10:38
  • happy to have helped! Could you then pls mark my comment as "answers the question"? This helps more folks to find this discussion :) Apr 14, 2023 at 13:51
  • Yes, it fixed my issue but according to my research, we shouldn't call this approval and allowance function from backend (solidity), we should always call these from front end only. Apr 15, 2023 at 14:12

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.