I can't call transferFrom() using remix

Hi everyone,

I'm trying to make a simple contract, that receives USDC as the method of payment.

Here is the code:

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

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

contract owned {
    address owner;

    constructor() {
        owner = msg.sender;

    modifier onlyOwner {
        require(msg.sender == owner,
        "Only the contract owner can call this function");

contract HandleUSDC is owned {
    address public _USDC = 0x2058A9D7613eEE744279e3856Ef0eAda5FCbaA7e;
    IERC20 public USDC = IERC20(_USDC);
    function allowSpender(address spender, uint256 amount) external returns(bool) {
        return USDC.approve(spender, amount);
    function sendFromTo(address from, address to, uint256 amount) external{
        USDC.transferFrom(from, to, amount);
    function checkBalance_USDC(address wallet) public view returns(uint) {
        return USDC.balanceOf(wallet);
    function checkAllowance(address owner, address spender) public view returns(uint) {
        return USDC.allowance(owner, spender);

So what I do is that I approve the contract ( address(this) ) to have access to 10 tokens, by calling allowSpender().
That works fine (I hope), but then:

  1. I can't check the allowance using checkAllowance() method, no matter in which order I put the addresses of msg.sender and address(this)
  2. When I try to call sendFromTo() using these parameters
    from: msg.sender
    to: address(this)
    amount: 10
    I get this error from remix:
    execution reverted: ERC20: transfer amount exceeds allowance

I don't understand what I'm doing wrong and how I can fix this issue :frowning:

BTW when I approve, MetaMask shows "Contract Interaction", instead of "Approve USDC spend limit".

P.S. I know similar questions have been asked, but none of them share the solution once they solve the problem!


I solved this issue.
The answer is: Remix can't do this! at least not as of now (November 2021)
I couldn't figure out how to do it with web3.js either. So I stopped using web3.js :slight_smile:
However it was incredibly easy to do it with ethers.js

This is my solidity code:

    event TransferReceived(address _from, uint256 _amount);
    event TransferSent(address _from, address _destAddr, uint256 _amount);

    address public _USDC = 0x2058A9D7613eEE744279e3856Ef0eAda5FCbaA7e;
    IERC20 public USDC = IERC20(_USDC);

    function getBalanceOf(address wallet) external view returns (uint256) {
        return USDC.balanceOf(wallet);

    function checkAllowance(address spender) external view returns (uint256) {
        return USDC.allowance(msg.sender, spender);

    function approveUSDC(uint256 amount) external {
        USDC.approve(address(this), amount);

    function depositUSDC(uint256 amount) external payable {
        uint256 erc20balance = USDC.balanceOf(msg.sender);
        require(amount <= erc20balance, "balance is low");
        USDC.transferFrom(msg.sender, address(this), amount);
        emit TransferSent(msg.sender, address(this), amount);

And this is my ethers.js code for depositing USDC (in react):

let transferFrom = await contract.depositUSDC(ethers.BigNumber.from(11))

before calling the transferFrom, you have to allow the contract to move your tokens around by calling the approve method in a similar fashion.

TL;DR trash web3.js and don't use remix if you want to develop around working with ERC20 tokens.