1

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

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

| improve this answer | |
2

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).

| improve this answer | |
  • Wow that's really useful and comprehensive information. Thanks a lot. – gbenroscience Jun 30 at 18:16
  • 1
    @gbenroscience: You're welcome :) – goodvibration Jun 30 at 18:26
  • 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. – gbenroscience Jun 30 at 18:52
  • please could you help me out with this question? ethereum.stackexchange.com/questions/84915/… – gbenroscience Jul 10 at 12:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.