I am trying to create my first smart contract based on https://docs.uniswap.org/protocol/guides/swaps/single-swaps I've deployed it on kovan test net using remix successfully but when trying to send the contract the amount of WETH9/DAI to swap i get this error https://kovan.etherscan.io/tx/0x1d038deff09b9dc338286bd9c8fe054ec247c05329072153a76fe545b6d7ab88 it seems that the smart contract is not withdrawing the amount to swap from metamask, I've tried to fix this myself for a few days now, but I'm stuck what is the problem here with the smart contract?

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
pragma abicoder v2;

import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';

interface IUniswapRouter is ISwapRouter {
    function refundETH() external payable;

contract Uniswap3 {
    // This example swaps WETH9/DAI for single path swaps.

    IUniswapRouter public constant uniswapRouter = IUniswapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
    address public constant DAI = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
    address public constant WETH9 = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;

    // For this example, we will set the pool fee to 0.3%.
    uint24 public constant poolFee = 3000;

    /// @notice swapExactInputSingle swaps a fixed amount of WETH9 for a maximum possible amount of DAI
    /// using the WETH9/DAI 0.3% pool by calling `exactInputSingle` in the swap router.
    /// @dev The calling address must approve this contract to spend at least `amountIn` worth of its WETH9 for this function to succeed.
    /// @param amountIn The exact amount of WETH9 that will be swapped for DAI.
    /// @return amountOut The amount of DAI received.
    function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) {
        // msg.sender must approve this contract

        // Transfer the specified amount of WETH9 to this contract.
        TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountIn);

        // Approve the router to spend WETH9.
        TransferHelper.safeApprove(WETH9, address(uniswapRouter), amountIn);

        // Naively set amountOutMinimum to 0. In production, use an oracle or other data source to choose a safer value for amountOutMinimum.
        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.
        ISwapRouter.ExactInputSingleParams memory params =
                tokenIn: WETH9,
                tokenOut: DAI,
                fee: poolFee,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0

        // The call to `exactInputSingle` executes the swap.
        amountOut = uniswapRouter.exactInputSingle(params);
        // refund leftover ETH to user
        (bool success,) = msg.sender.call{ value: address(this).balance }("");
        require(success, "refund failed");
    // important to receive ETH
    receive() payable external {}
  • Have you figured out what causes this fucking STF error?
    – Pei
    Aug 30 '21 at 19:56

Before calling the swapExactInputSingle of your contract you have to approve the contract to take the wETH from your account to the smart contract.

Like so (brownie test example):

   {"from": accounts[0]},

This is what the // msg.sender must approve this contract line means.

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.