Uniswap: transferFrom error Dai/insufficient-allowance

I am following Uniswap documentation to swap (kovan) DAI to ETH using swapExactTokensForETH.

However, REMIX IDE always gives this error when I attempt to run my function.
image

If I ignore and just send transaction, I get [“Dai/insufficient-allowance” on transferFrom] error in my transaction.

I double checked the amount of DAI I have. I have ~11 DAIs.

It seems I have a problem setting allowance. Can someone help?

Thank you in advance.

:computer: Environment
IDE: REMIX
I’m importing github IERC20.sol
import “https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol”;

:memo:Details
I’m having the same issue as this person experienced. But this person disappeared without any solution :frowning: "Dai/insufficient-allowance" on transferFrom

:1234: Code to reproduce

...
address internal constant UNISWAP_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;

IUniswapV2Router02 public uniswapRouter;
address private kovanDAI = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
address private myAccount = msg.sender;

IERC20 private daiToken = IERC20(kovanDAI);

constructor() payable {
  uniswapRouter = IUniswapV2Router02(UNISWAP_ROUTER_ADDRESS);
}

function convertDAItoETH(uint daiAmountIn, uint minETHAmountToReceieve) public payable {
  // here I even tried to add one more approve line like below
  // require(daiToken.approve(address(this), daiAmountIn), "approve failed");
  require(daiToken.transferFrom(myAccount, address(this), daiAmountIn), "transferFrom failed");
  require(daiToken.approve(address(uniswapRouter), 0), "approve failed");
  require(daiToken.approve(address(uniswapRouter), daiAmountIn), "approve failed");
  uint deadline = block.timestamp + 15; // using 'now' for convenience, for mainnet pass deadline from frontend!
  uniswapRouter.swapExactTokensForETH(daiAmountIn, minETHAmountToReceieve, getPathForDAItoETH(), address(this), deadline);
}

function getPathForETHtoDAI() private view returns (address[] memory) {
  address[] memory path = new address[](2);
  path[0] = uniswapRouter.WETH();
  path[1] = kovanDAI;

  return path;
}
...
1 Like

This question also posted at StackExchange: https://ethereum.stackexchange.com/questions/90960/always-get-dai-insufficient-allowance-error

1 Like

Hi @seanoh1989,

Welcome to the community :wave:

Have you approved an allowance for the amount required to your contract?
The token holder needs to first set an allowance for your contract in one transaction and then can call convertDAItoETH in a second transaction.

See: Example on how to use ERC20 token in another contract.

1 Like

Hi @abcoathup,

Thank you for reply.

I added

daiToken.approve(address(this), daiAmountIn);

right above transferFrom call, but I still get the same issue.

I tried to separate them so I can make two separate transaction, and approve transaction is successful, but transferFrom still gives me the error.

Here’s the transaction that approved the allowance: https://kovan.etherscan.io/tx/0xdc5f0506a4186b85153047939b4cd8900b90711a409d03a4be03c0ee6c974524,
followed by failed (Fail with error ‘Dai/insufficient-allowance’) transaction: https://kovan.etherscan.io/tx/0x6d1cdb65cef70f4cf03b7b1e57930c8d203a6c40e51bbcebd58721b0ecd5598f

Again, I have 11.5 DAI right now :frowning:

Thank you.

1 Like

Hi @seanoh1989, did you convert the amount to be approved to Wei before calling the approve method?

And besides your wallet only has 9.5 Dai

2 Likes

Yes, I typed small amount such as 100000000.

As for the 9.5 DAIs, I tried to convert it through Uniswap website just in case my wallet or the token itself has a problem. It worked just fine on the website. So definitely I’m doing something wrong :joy:

1 Like

@abcoathup so far, this is what I found.

if I call token.approve(address(this), amount), for some reason I approve my contract to use amount of token in my contract.

This doesn’t make any sense to me.

isn’t approve supposed to know the _owner is the account, and _spender is address(this) (the contract)?

Related question was created separately here: https://ethereum.stackexchange.com/questions/91063/ierc20-approvespender-amount-thinks-the-owner-is-also-the-contract/91066#91066

Thank you.

1 Like

Hi @seanoh1989,

Looking at the two transactions they were both to the same contract.

You need to call

  1. The token from your EOA to approve an allowance for your contract
  2. The contract from your EOA to do what you need to do and this can call transferFrom

I recommend going through: Example on how to use ERC20 token in another contract

1 Like

Hi @abcoathup,
I followed the example and successfully deployed the token and contract, but it seems approve is not working for some reason.

This is the contract of the token (DAI at Kovan): https://kovan.etherscan.io/address/0x61c3e04251b526057eabe8296a33a2212c366bbc

pragma solidity >=0.6.0 <0.8.0;

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

contract Dai is ERC20 {
    constructor () public ERC20("Dai Stablecoin", "DAI") {}
}

when I call token.balanceOf("0x62dE96237146061E4a71B7c89b1b114185c78695") where address is my account number from Metamask wallet, I get 0 balance. However I have 5 DAI tokens in the account.

Also, when I call approve, I can see the transaction with Approve call went through (tx: https://kovan.etherscan.io/tx/0xa37011bc138d527e5e032a5aa8f6ed14f19aa3c1a52c9150bce778b844da9dd0), but when I check the allowance, I see 0.

I feel like I’m really close to the goal I was trying to do. Just need a little bit of help.

Thanks for helping.

1 Like

Hi @seanoh1989,

The following contract has a total supply of 0 tokens as no tokens are ever minted.

pragma solidity >=0.6.0 <0.8.0;

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

contract Dai is ERC20 {
    constructor () public ERC20("Dai Stablecoin", "DAI") {}
}

If you want to create a fixed supply of tokens, you could use something like the example in: Simple ERC20 token example

In the constructor this mints tokens to the deployer of the contract using _mint(msg.sender, initialSupply);

So, I had a misunderstanding about Tokens already publishes vs Token contract I was writing.

I ended up not using REMIX and my own smart contracts.

I used Web3js and loaded publishes DAI contract.

let token = new web3.eth.Contract(erc20ABI.abi, daiContractAddress)
token.methods.approve(uniswapRouter02Address, tokenAmountIn)
    .send({ from: web3.eth.defaultAccount, gas: gasLimit })
    ... // some listeners

Using the same approach, I was able to load other contracts I needed and use them.

The problems I didn’t understand, or still don’t know are

  1. I cannot approve tokens already published through REMIX
  2. If I call approve from a contract, the contract approves the fund to be used for the spender
  3. Those YouTube videos about writing contract for ERC20 tokens are MY OWN tokens, so I shouldn’t do that if I’m not planning on publishing my own tokens.

Thank you for being patient and helping me @abcoathup.

1 Like

Hi @seanoh1989,

Glad to hear that you were able to use tokens that you held (rather than created).

If you are an ERC20 token holder (you have a non-zero balance of the token) you should be able to approve an allowance to another account, and if that account is a contract, when you call a function on that contract it can call transferFrom to transfer an amount of tokens within the allowance you set.

If you call approve from a contract, then the contract needs to be the token holder (have a non-zero balance of the token) in order for the account with the allowance to call transferFrom.