2

I am using Uniswap's interface Router02 and have been able to execute all swap functions correctly with one specific exception: swap WETH to ETH.

In the contract below, function swapExactTokensForETH() works correctly if the source token is whichever except WETH (i.e.: DAI, UNI):

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;

import "./IUniswap.sol";
import "./IERC20.sol";

contract Uniswap {

    // Uniswap contract addresses at Ropsten
    address internal constant UNISWAP_ROUTER_ADDRESS =
        0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;

    IUniswap uniswap;

    constructor() {
        uniswap = IUniswap(UNISWAP_ROUTER_ADDRESS);
    }

    // Swaps an exact amount of tokens for as much ETH as possible, along the route determined by the path
    function swapExactTokensForETH(
        address tokenIn,
        uint256 amountIn,
        uint256 amountOutMin
    ) external {
        // move 'amountIn' tokens from User to this Contract (User's approval is required before the transfer)
        _transferToken(tokenIn, msg.sender, address(this), amountIn);

        // an array of token addresses (tokens we want to trade). path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
        address[] memory path = new address[](2);
        path[0] = tokenIn;
        path[1] = uniswap.WETH();

        // approve to the Router to withdraw this 'amountIn' tokens
        IERC20(tokenIn).approve(address(uniswap), amountIn);

        // using 'now' for convenience, but should be sent from frontend!
        uint256 deadline = block.timestamp + 15;

        // Swap Tokens for ETH
        uniswap.swapExactTokensForETH(
            amountIn,
            amountOutMin,
            path,
            msg.sender,
            deadline
        );
    }

    function _transferToken(
        address token,
        address from,
        address to,
        uint256 amount
    ) internal {
        require(
            IERC20(token).allowance(from, to) >= amount,
            "Uniswap approval is missing"
        );
        IERC20(token).transferFrom(from, to, amount);
    }
  //...
}

However, when the swap is WETH to ETH, I get the following error:

Fail with error 'UniswapV2Library: IDENTICAL_ADDRESSES'

In fact, the error makes sense because the pair will have two identical addresses:

  • path[0] = tokenIn; => This will be WETH contract address

  • path[1] = uniswap.WETH(); => When conversion is to ETH, Uniswap requires to convert it in WETH by default, so it will also be WETH contract address

Therefore, how should I define the pair or what change I should apply in order to effectively swap WETH to ETH?

1
  • Did you figure a solution? I have the same problem for swapping ETH to WETH.
    – Benny
    Feb 7, 2022 at 20:27

2 Answers 2

2

You must use the WETH contract directly. Check https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#writeContract and the deposit()/withdraw() functions.

0

The message UniswapV2Library: IDENTICAL_ADDRESSES is generic. ETH is a native value of blockchain and WETH is a token (like any token on the network). This token is paired with native ETH.

The function is renamed swapExactTokensForETH, but the actual exchange is for WETH. No tokens have a liquidity pool or exchange directly to native ETH.

For the sake of design and ease, the Uniswap standard works with wrapped ETH, (WETH), and there is no way to directly exchange tokens for ETH.

On the other hand, if the token has transfer fees it is recommended to use the correct function: https://docs.uniswap.org/protocol/V2/reference/smart-contracts/router-02

As suggested by the colleague above, create a call to the WETH contract to withdraw to ETH.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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