here is my contract I'm minting an nft against erc20 token, but it will always give revert in the first condition of if because the transfer from function throws an error of insufficient allowance but I'm allowing the contract to spend on my behalf still it throws revert kindly guide me what is the reason causing this error.

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

// import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "antematter/usd.sol";

contract MyNft is ERC721, Ownable {
    uint256 public constant MAX_SUPPLY = 50;
    uint256 public currentSupply;
    uint256 public fee = 10 * (10**18);
    address[] public minters;
    TetherUsd anteMatter;

    constructor() ERC721("MyToken", "MTK") {
        anteMatter = new TetherUsd();

    function safeMint(uint256 tokenId) public {
        anteMatter.mint(msg.sender, fee * 2);
        anteMatter.approve(getAdd(), fee);
        require(currentSupply < MAX_SUPPLY);
        require(anteMatter.balanceOf(msg.sender) > fee, "insufficient usdt");
        if (currentSupply == 0) {
            // anteMatter.approve(getAdd(), fee);
            anteMatter.transferFrom(msg.sender, getAdd(), fee);
        _safeMint(msg.sender, tokenId);

    function getAdd() public view returns (address) {
        return address(this);

1 Answer 1


anteMatter.approve(getAdd(), fee); won't work. If you check the approve() function in ERC20.sol from openzeppelin, you'll see it's

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;

(where _approve() contains the actual logic), meaning that you're approving spender, to spend msg.sender's tokens. In your case, since you're calling approve from your contract, msg.sender is your contract, which means you're approving your contract to spend its own tokens (which is pointless, of course). For it to work, you need msg.sender to be the EOA that's trying to mint, meaning that you need to make the call from your EOA directly (which is the reason why when you swap a token for the first time on a DEX, you're asked to sign 2 transactions, the first is the approval, the 2nd is the actual swap), so that should be handled in your frontend

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.