6

I am trying to do the reverse action of what I did in this question: Basically sell/swap some arbitrary token and receive ether on Uniswap V2 using IUniswapV2Router02.

Here is what I have done:

 contract SellTokens{
    
       IUniswapV2Router02 usi = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
          
    function sellDai(uint256 daiQty , address cryptoToken) public payable returns(uint256){

//address cryptoToken = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;//0x00D811B7d33cECCFcb7435F14cCC274a31CE7F5d//multiDaiKovan;

    uint256 ethAmountDerivable = getEstimatedTokenForETH(daiQty , cryptoToken)[0];
 
  uint deadline = now + 300; // using 'now' for convenience, for mainnet pass deadline from frontend!

    usi.swapExactTokensForETH(daiQty , ethAmountDerivable, getPathForTokenToETH(cryptoToken), address(this), deadline);

   return ethAmountDerivable;

}
    
    function getEstimatedTokenForETH(uint daiQty , address crypto) public view returns (uint[] memory) {
        return usi.getAmountsIn(daiQty, getPathForTokenToETH(crypto));
      }
    
     function getPathForTokenToETH(address crypto) private view returns (address[] memory) {
        address[] memory path = new address[](2);
        path[0] = crypto;
        path[1] = usi.WETH();
        
        return path;
      }
    
    }

When I call sellDai from truffle console using:

c.sellDai(web3.utils.toWei('0.02'),'0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa',{value: 3000000000000000})

I get the following output

The status says: Fail with error 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'

What could be the issue, please?

EDIT

I changed the getAmountsIn function call to getAmountsOut, and the error changed from INSUFFICIENT_OUTPUT_AMOUNT to TransferHelper: TRANSFER_FROM_FAILED.

EDIT 2

After the admonition to approve the token before transfer, I did this:

function sellDai(uint256 daiQty , address cryptoToken) public payable returns(uint256){

//address cryptoToken = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;//0x00D811B7d33cECCFcb7435F14cCC274a31CE7F5d//multiDaiKovan;

  uint256 ethAmountDerivable = getEstimatedTokenForETH(daiQty , cryptoToken)[0];
  ethAmountDerivable = ethAmountDerivable.mul(10).div(11);// divide by 1.1
 
  uint deadline = now + 300; // using 'now' for convenience, for mainnet pass deadline from frontend!

  IERC20 dai = IERC20(cryptoToken);
  dai.approve(address(this), 0);
  dai.approve(address(this), daiQty);

    usi.swapExactTokensForETH(daiQty , ethAmountDerivable, getPathForTokenToETH(cryptoToken), address(this), deadline);

   return ethAmountDerivable;

}

But it still didnt work. Any ideas please. Here is the transaction

Thanks again

1
  • If you want help, at least post tidy code. And if you solve your problem, it would be harmonious to provide the fix.
    – P i
    Commented Jun 16, 2021 at 10:52

3 Answers 3

2

I think it's because you are using getAmountsIn instead of getAmountsOut. You are starting with the input amount (Dai) and want to get the output amount, not the reverse. It's therefore returning an amount denominated in Dai, which is a much higher number than the equivalent $ value of Eth, so the trade fails the check for the minimum output (which is way too high) https://github.com/Uniswap/uniswap-v2-periphery/blob/460ffcda51492bef3b191fdaf50092e0d35b66c2/contracts/libraries/UniswapV2Library.sol#L52

14
  • I changed it to getAmountsOut, now it says: Fail with error 'TransferHelper: TRANSFER_FROM_FAILED' kovan.etherscan.io/tx/… Commented Jun 30, 2020 at 18:41
  • please check my edit Commented Jun 30, 2020 at 18:50
  • 1
    You can't interact with UniswapV2Router2 to change the allowance amount in the Dai contract, you have to call the Dai contract itself. You need an ERC20 interface like github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/… and have IERC20 dai = IERC20(dai_address); dai.approve(address(this), amount_to_approve); Commented Jun 30, 2020 at 19:24
  • 1
    Definitely before :) Commented Jun 30, 2020 at 21:53
  • 1
    Alright thanks for your help, I finally got it working. Commented Jul 1, 2020 at 4:30
5

Here is how I debug your issue (which is what you could have easily done yourself):

  1. Search 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D on https://etherscan.io
  2. Click on the Contract tab and scroll down to the Contract Source Code text box
  3. Search for function swapExactTokensForETH in the source code
  4. Search for INSUFFICIENT_OUTPUT_AMOUNT inside that function
  5. Conclude what input parameter may cause the related error

I did some of this work for you.

The contract source code is available here, and the relevant part of it is:

    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
        );
        _swap(amounts, path, address(this));
        IWETH(WETH).withdraw(amounts[amounts.length - 1]);
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }

As you may understand, you should reduce the value of ethAmountDerivable, which is what you are passing to the function as the input parameter amountOutMin (which is designated for your own protection, in case the output amount is smaller than what you define as your minimum limit).

2
  • Wow that's really useful and comprehensive information. Thanks a lot. Commented Jun 30, 2020 at 18:16
  • please check my edit. I checked the contract code and saw where the error message occurred. It has something to do with my contract address, but I cant tell what could be wrong. Commented Jun 30, 2020 at 18:52
0

The problem with your code seems the approve function you called before the swap function swapExactTokensForETH.

You have approved it for your smart contract address which is wrong, it should be approved for the Uniswap router address: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D

Let me know if this works.

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.