I have a multi contract dapp going with a few ERC-20 tokens.

My intermediary contract that the end user owns calls a function which mints new Tokens. The Token contract itself holds these. When some later condition is met, the user then completes their action and the Tokens should be send from the contract to the user. The last item here is failing with the error that

contract Generator {
    constructor(address tokenAddress) {
        token = Token(tokenAddress);

    function createUser(string calldata name) public {
        User user = new User(name, token)

contract User is Ownable {
    Token token;
    constructor(string memory name, Token _token) {
        token = _token;

    function startAction() public {
        // after mintSelf resolves, etherscan shows 5 TOKEN as expected

    function completeAction() public {
        // right here is where I get the error
        transferFrom(address(token), owner(), 5);

contract Token is ERC20 {
    constructor() ERC20("Token", "TOKEN") {
        _mint(address(this), 0);

    function mintSelf(uint256 qty) public {
        _mint(address(this), qty);

Everything goes great and I confirm Token has 5 TKN on etherscan for the first part where it calls selfMint

When I can resolve() is when I get the error

Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32603,"message": "execution reverted: ERC20: insufficient allowance","data":{"originalError":{" code":3,"data":"0x.....000000"," message":"execution reverted: ERC20: insufficient allowance"}}}, method="estimateGas", transaction={"from":"0x...","to":"0x...","data":"0x...","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.3)

What am I missing what account isn't funded properly?

Is this because the calling contracts don't have proper permissions to send Tokens on the contracts behalf? If so how/where would I add that in?

Or is it that it wants some contract to have ETH for gas, but none of them hold it. I want the original msg.sender to pay for all the gas.

I added another call in between to ensure it was going right and now I'm not getting an error but I'm also not getting the appropriate behavior

Instead of User.completeAction calling transferFrom, it's calling

    token.sendTo(owner(), 5);

whose implementation looks like

    function sendTo(address to, uint256 qty) public {
        _transfer(address(this), to, qty);

I'm not getting any errors now, but the token is not moving back to the User's owner! I still see it in the Token's contract on etherscan, and I don't see any transactions out :-\

1 Answer 1


I think your issue is fixed because of the update. you need to understand the main working of transferFrom. transfer from function is used to transfer the funds from some other account which are approved for the caller to his account.while transfer(_transfer) function is used to transfer you tokens to some one else.

  • I'm not getting an error after that update, but I'm also not seeing the coins actually move though Mar 2, 2022 at 17:06
  • 1
    Contract it self has no tokens. Tokens are with the user. User should approve the payment to contract and then contract transfers those tokens to address. what you can do is from client side when user clicka button first you call the approve function to approve funds to the contract. Then contract brings those funds into it self useing transferfrom function and then you can use sendto to send it to next address. Mar 7, 2022 at 9:55

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.