0

I'm trying to swap ETH for WBTC in a smart contract automatically after receiving ETH in Solidity. What's the best option? Using the uniswap swap method for example? Can anyone help me? Thanks for your help!

[Edit] Following @Mehran Ra's reply, here's my code:

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

import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract EthToWBTC {
    // For Uniswap v3, addresses depend on network.
    // This is for Ethereum Mainnet. You need the appropriate address for your network.
    ISwapRouter public immutable uniswapRouter;
    address public constant WBTC = 0x577D296678535e4903D59A4C929B718e1D575e0A; // Mock WBTC address, replace with actual WBTC token address.
    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    // Set the Uniswap V3 router address when deploying the contract
    constructor(ISwapRouter _uniswapRouter) {
        uniswapRouter = _uniswapRouter;
    }

    // Swap ETH for WBTC
    // The calldata for the swap will be constructed in this function
    function swapETHforWBTC(uint256 deadline, uint24 poolFee) external payable {
        require(msg.value > 0, "Must send ETH to swap");

        // Set the parameters for the swap
        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
        tokenIn: WETH,
        tokenOut: WBTC,
        fee: poolFee,
        recipient: msg.sender,
        deadline: block.timestamp + deadline,
        amountIn: msg.value,
        amountOutMinimum: 0,
        sqrtPriceLimitX96: 0
    });

        // Execute the swap from ETH to WBTC
        uniswapRouter.exactInputSingle{value: msg.value}(params);
    }

    // This function is required so your contract can receive ETH.
    receive() external payable {}
}

I deployed the contract on Remix VM - Mainnet fork with the following address: "0xE592427A0AEce92De3Edee1F18E0157C05861564" (seems to be the address of Uniswap V3: Router on ETH). The contract is correctly deployed.

Next, I try to swap with 1 ETH as msg.value by calling swapETHforWBTC(300, 3000) and get the following error:

transact to EthToWBTC.swapETHforWBTC errored: Error occured: revert.

revert
    The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the     value you send should be less than your current balance.
Debug the transaction to get more information.
[vm]from: 0x5B3...eddC4to: EthToWBTC.swapETHforWBTC(uint256,uint24)     0x86c...e8497value: 1000000000000000000 weidata: 0x46a...00bb8logs: 0hash:     0x086...61b0f
status  0x0 Transaction mined but execution failed

I don't understand the error since the method is payable, I guess it's a problem with using the Uniswap router.

Any ideas? Thanks for your help

1 Answer 1

2

Try this code, This code uses UniSwap version 3. Please input the router address when deploying the contract :

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

import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract EthToWBTC {
    // For Uniswap v3, addresses depend on network.
    // This is for Ethereum Mainnet. You need the appropriate address for your network.
    ISwapRouter public immutable uniswapRouter;
    address public constant WBTC = 0x577D296678535e4903D59A4C929B718e1D575e0A; // Mock WBTC address, replace with actual WBTC token address.
    
    // Set the Uniswap V3 router address when deploying the contract
    constructor(ISwapRouter _uniswapRouter) {
        uniswapRouter = _uniswapRouter;
    }

    // Swap ETH for WBTC
    // The calldata for the swap will be constructed in this function
    function swapETHforWBTC(uint256 deadline, uint24 poolFee) external payable {
        require(msg.value > 0, "Must send ETH to swap");

        // Set the parameters for the swap
        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
            tokenIn: uniswapRouter.WETH9(),
            tokenOut: WBTC,
            fee: poolFee,
            recipient: msg.sender,
            deadline: deadline,
            amountIn: msg.value,
            amountOutMinimum: 0,
            sqrtPriceLimitX96: 0
        });

        // Execute the swap from ETH to WBTC
        uniswapRouter.exactInputSingle{value: msg.value}(params);
    }

    // This function is required so your contract can receive ETH.
    receive() external payable {}
}
3
  • Thank you for your reply. In fact, I want my contract to retrieve the msg.value and automatically swap it into WBTCs. These WBTCs will remain in the contract afterwards. I tested your code on Remix VM Mainnet fork and I get this error (1 ETH as msg.value): "revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information." Do you have any idea how to proceed? Thanks in advance Commented Jan 1 at 19:34
  • Because you need to communicate with UniSwap, you should test on the network that UniSwap supports and give the address of that network to its interface.
    – Mehran Ra
    Commented Jan 2 at 18:45
  • ok @Mehran Ra I understand but I think I used the correct address of Uniswap Router V3 when deploying. On the other hand, when I thought about it I replaced the uniswapRouter.WETH9() code with address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 because there didn't seem to be a uniswapRouter.WETH9() method. Perhaps this is the error. PS: I've edited the current post with my current tested code Commented Jan 5 at 10:16

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.