First, let me apologize because I've seen this question asked multiple times but I can't figure it out still.

  function setAllowance(address tokenAddr, uint256 amount) external payable {
    IERC20(tokenAddr).safeIncreaseAllowance(address(this), amount * 10**18);

  function getAllowance(address tokenAddr) external view returns (uint256) {
    return IERC20(tokenAddr).allowance(msg.sender, address(this)) / 10**18;

This is my function in solidity. I'm calling it from React so within this function the caller/msg.sender is my external metamask wallet address. I want my contract to be able to send tokens on behalf of the external metamask wallet. However, the allowance does not increase. I believe my setAllowance is wrong, but it doesn't have a "owner" & "spender" parameter, only "spender" which is my contract (ie. address(this)).

So how do I know who the spender is getting the allowance from, because I want it to be the external metamask wallet, but clearly that is not happening and it's getting an allowance from something else.

I want to add in that I swapped address(this) and msg.sender, but I don't want my external wallet to have an allowance from the contract, I need it the other way around. (though in this case, the allowance did increase).

Edit 1: Im using import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol" and the function:

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));

Edit 2: Testing it on Mumbai network (Polygon testnet)

Faucet: https://faucet.polygon.technology/

Using: Test ERC20 Plasma from this faucet on Mumbai

Testing Token: https://polygonscan.com/token/0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1

  • Hi, which interface are you implementing? github.com/OpenZeppelin/openzeppelin-contracts/blob/master/… is it this one? Cannot find any IERC20 that implements safeIncreaseAllowance() Commented Jan 30, 2022 at 19:54
  • @StanislavSvědiroh. I can replace safeIncreaseAllowance with approve from that and still get the same issue. for the function you mentioned, got it from this: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
    – swazzy123
    Commented Jan 30, 2022 at 20:25
  • But this interface doesn't even have safeIncreaseAllowance() method. Using this you need to call approve(address spender, uint256 amount) to be able to set allowance. Commented Jan 30, 2022 at 20:29
  • Sorry updated comment, misread
    – swazzy123
    Commented Jan 30, 2022 at 20:29
  • What does your token implementation inherit from? Commented Jan 30, 2022 at 20:32

2 Answers 2


Are you talking about this contract?


If so, I would personally just create my own interface, because the USDT implementation is kinda wild:

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

interface IERC20 {
    function balanceOf(address owner) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function allowance(address owner, address spender)
        returns (uint256);

    function increaseAllowance(address spender, uint256 addedValue)
        returns (bool);

    function decreaseAllowance(address spender, uint256 subtractedValue)
        returns (bool);

You can even delete the approve() function if you won't be using it.

Note that this will NOT work the same way on mainnet, because there's a completely different implementation of an older ERC20 version.

  • I'm on mumbai testnet, sorry think my edit on the question happened while u wrote out this answer. Faucet: faucet.polygon.technology Using: Test ERC20 Plasma from this faucet on Mumbai Token: polygonscan.com/token/… Lets ignore USDT for now, just a generic ERC20 token because I want to be able to pass any erc20 token with 18 decimals. Also, how does making your own interface even work? Don't you need to implement it? Will IERC20(tokenArr) still work?
    – swazzy123
    Commented Jan 30, 2022 at 21:07
  • Making your own interface works the same way as importing it from github. After all, import statement is just a way to tell the compiler to copy the whole referrenced code to that exact line. Commented Jan 31, 2022 at 7:50
  • Connected to mumbai and claimed those Test ERC20 tokens. The correct contract for it is: mumbai.polygonscan.com/token/…. Other than that I was only able to get my balance from solidity, they seem to only have approve function but I wasn't been able to get it working. This is their implementation for TypeScript and their docs github.com/maticnetwork/maticjs-plasma/blob/main/src/erc20.ts docs.polygon.technology/docs/develop/ethereum-polygon/plasma/… Sorry, I don't know much about the inner workings of polygon. Commented Jan 31, 2022 at 8:37

Thanks to @Ismael♦ for the clue, helped me go in the right direction. Don't think I can upvote the comment cause I'm a new user (only getting flag option).


  1. Get Token ABI from etherscan
  2. initialize token contract
 new ethers.Contract(tokenAddress, tokenAbi, signer)
  1. call approve on token contract (giving address of ur deployed contract) THEN

  2. proceed to transfer tokens from their wallet using your own contract

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.