Search code examples
transactionsethereumsoliditymetamask

Solidity - transfer amount exceeds spender allowance


The code looking correct,approving token before transfering, but failing with error: "transfer amount exceeds spender allowance" Sender account is having more than required token balance.

Any ideas? Contract: https://rinkeby.etherscan.io/address/0x2a855c479b14443489963eef90ad449ecdf40cf5#writeContract

pragma solidity ^0.7.0;  


interface IERC20 {
   function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
   function approve(address spender, uint256 amount) external returns (bool); 
   function transfer(address recipient, uint256 amount) external returns (bool);
} 
 
contract FundTokenContract { 
    address public owner;   
     
    constructor(){ 
        owner = msg.sender;
    }   
    
    modifier OnlyOwner() {
        require(msg.sender == owner, "Only owner can call this function.");
        _;
    } 
    
     function fundToken(address tokenAddress, uint amount ) external {  
        require(amount > 0);  
        IERC20(tokenAddress).approve(address(this), amount); 
        IERC20(tokenAddress).transferFrom(msg.sender ,address(this), amount);  
    }  
      
      
    function withdrawToken(address _tokenAddress, address  _recipient, uint _amount) public  OnlyOwner returns (bool){  
        IERC20(_tokenAddress).transfer(_recipient, _amount);
        return true;
    }  
}

enter image description here

enter image description here


Solution

  • When your contract executes the tokenAddress function approve(), the msg.sender within the approve() function is your contract (not the user initiating the transaction).

    Which effectively approves "your contract" (first argument address(this)) to spend "your contract"s (msg.sender) funds.

    Then it's trying to transferFrom() the user address, but it doesn't have the approval.


    If you want your contract to spend tokens that belong to another user, they need to execute the approve(<yourContract>, <amount>) from their address directly (not through a contract).

    Note: See the TLDR in this answer, it shows how this requirement is useful.