0
votes

I'm trying to implement a Solidity smart contract that will send deployed tokens from address A to address B.

Address A - should be the current user calling the contract function "stake". Address B - should be a custom wallet address from outside.

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";

contract TokenTransfer {
    IERC20 _token;

    constructor(address token) public {
        _token = IERC20(token);
    }

    function stake(address to, uint amount) public {
        _token.approve(address(this), amount);
        require(_token.allowance(msg.sender, address(this)) >= amount, "Token allowance too low");
        bool sent = _token.transferFrom(msg.sender, to, amount);
        require(sent, "Token transfer failed");
    }
}

Current implementation returns allowance error: "Token allowance too low"

I'm running it with MetaMask (injected web3). I expected MetaMask to open a simple transfer window with my token.

1

1 Answers

1
votes

In order to use transferFrom() from your contract, the token holder needs to approve() the spender (your contract) directly from their address. Not through your contract.


_token.approve(address(this), amount);

This snippet approves TokenTransfer (address(this)) to spend TokenTransfer's (the approve() function invoker) tokens, because the function is effectively invoked from the TokenTransfer's address.

That's why the require() condition is failing. The token holder (msg.sender) hasn't approved your contract (address(this)) to spend their tokens. If you replaced the condition to _token.allowance(address(this), address(this)), then it would pass (see the previous paragraph).