title: Implementing Uniswap v3 API single swap example on scaffold-eth - ERROR: cannot estimate gas
body: <p>Using <a href="https://github.com/scaffold-eth/scaffold-eth" rel="nofollow noreferrer">scaffold-eth</a> to implement this single swap example from the <a href="https://docs.uniswap.org/protocol/guides/swaps/single-swaps" rel="nofollow noreferrer">uniswap documentation</a>.</p>
  <p>Pretty much just copied and pasted the code and was able to deploy it successfully to rinkeby:</p>
  <pre class="lang-js prettyprint-override"><code>//SPDX-License-Identifier: MIT
  pragma solidity &gt;=0.8.0 &lt;0.9.0;
  pragma abicoder v2;
  
  import &quot;hardhat/console.sol&quot;;
  import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
  import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
  
  contract YourContract {
    // For the scope of these swap examples,
    // we will detail the design considerations when using
    // `exactInput`, `exactInputSingle`, `exactOutput`, and  `exactOutputSingle`.
  
    // It should be noted that for the sake of these examples, we purposefully pass in the swap router instead of inherit the swap router for simplicity.
    // More advanced example contracts will detail how to inherit the swap router safely.
  
    ISwapRouter public immutable swapRouter;
  
    // This example swaps DAI/WETH9 for single path swaps and DAI/USDC/WETH9 for multi path swaps.
  
    address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address public constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
  
    // For this example, we will set the pool fee to 0.3%.
    uint24 public constant poolFee = 3000;
  
    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }
  
    /// @notice swapExactInputSingle swaps a fixed amount of DAI for a maximum possible amount of WETH9
    /// using the DAI/WETH9 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 DAI for this function to succeed.
    /// @param amountIn The exact amount of DAI that will be swapped for WETH9.
    /// @return amountOut The amount of WETH9 received.
    function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) {
        // msg.sender must approve this contract
  
        // Transfer the specified amount of DAI to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountIn);
  
        // Approve the router to spend DAI.
        TransferHelper.safeApprove(DAI, address(swapRouter), 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 =
            ISwapRouter.ExactInputSingleParams({
                tokenIn: DAI,
                tokenOut: WETH9,
                fee: poolFee,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0
            });
  
        // The call to `exactInputSingle` executes the swap.
        amountOut = swapRouter.exactInputSingle(params);
    }
  
    /// @notice swapExactOutputSingle swaps a minimum possible amount of DAI for a fixed amount of WETH.
    /// @dev The calling address must approve this contract to spend its DAI for this function to succeed. As the amount of input DAI is variable,
    /// the calling address will need to approve for a slightly higher amount, anticipating some variance.
    /// @param amountOut The exact amount of WETH9 to receive from the swap.
    /// @param amountInMaximum The amount of DAI we are willing to spend to receive the specified amount of WETH9.
    /// @return amountIn The amount of DAI actually spent in the swap.
    function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) {
        // Transfer the specified amount of DAI to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountInMaximum);
  
        // Approve the router to spend the specifed `amountInMaximum` of DAI.
        // In production, you should choose the maximum amount to spend based on oracles or other data sources to achieve a better swap.
        TransferHelper.safeApprove(DAI, address(swapRouter), amountInMaximum);
  
        ISwapRouter.ExactOutputSingleParams memory params =
            ISwapRouter.ExactOutputSingleParams({
                tokenIn: DAI,
                tokenOut: WETH9,
                fee: poolFee,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountOut: amountOut,
                amountInMaximum: amountInMaximum,
                sqrtPriceLimitX96: 0
            });
  
        // Executes the swap returning the amountIn needed to spend to receive the desired amountOut.
        amountIn = swapRouter.exactOutputSingle(params);
  
        // For exact output swaps, the amountInMaximum may not have all been spent.
        // If the actual amount spent (amountIn) is less than the specified maximum amount, we must refund the msg.sender and approve the swapRouter to spend 0.
        if (amountIn &lt; amountInMaximum) {
            TransferHelper.safeApprove(DAI, address(swapRouter), 0);
            TransferHelper.safeTransfer(DAI, msg.sender, amountInMaximum - amountIn);
        }
    }
  }
  </code></pre>
  <p>Also learned to edit my deployer to add in the args for the constructor, and made sure to pass the SwapRouter address from <a href="https://docs.uniswap.org/protocol/reference/deployments" rel="nofollow noreferrer">here</a>:</p>
  <pre class="lang-js prettyprint-override"><code>await deploy(&quot;YourContract&quot;, {
      // Learn more about args here: https://www.npmjs.com/package/hardhat-deploy#deploymentsdeploy
      from: deployer,
      args: [ '0xE592427A0AEce92De3Edee1F18E0157C05861564' ],
      log: true,
      waitConfirmations: 5,
    });
  </code></pre>
  <p>This all worked, and I am able to see this in the debug console on my local scaffold-eth, running on rinkeby:</p>
  <p><a href="https://i.stack.imgur.com/P4ndy.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/P4ndy.png" alt="enter image description here" /></a></p>
  <p>I also made sure to have enough funds in my wallet for gas, etc:</p>
  <p><a href="https://i.stack.imgur.com/VlGYU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VlGYU.png" alt="enter image description here" /></a></p>
  <p>When I try to hit send in the swapExactInputSingle function for any amount of DAI, I get the following error every time:</p>
  <pre><code>{
     &quot;reason&quot;:&quot;cannot estimate gas; transaction may fail or may require manual gas limit&quot;,
     &quot;code&quot;:&quot;UNPREDICTABLE_GAS_LIMIT&quot;,
     &quot;error&quot;:{
        &quot;code&quot;:-32000,
        &quot;message&quot;:&quot;execution reverted&quot;
     },
     &quot;method&quot;:&quot;estimateGas&quot;,
     &quot;transaction&quot;:{
        &quot;from&quot;:&quot;0xF59FBfd44C9e495542D46109F81416bd3fC38Ed7&quot;,
        &quot;to&quot;:&quot;0xcFc57b48365133105F6877a02126673B7b906a55&quot;,
        &quot;data&quot;:&quot;0x73bd43ad000000000000000000000000000000000000000000000000000000000000000a&quot;,
        &quot;accessList&quot;:null
     }
  }
  </code></pre>
  <p>I get this error as soon as I hit send, and am never prompted to approve my DAI or anything else. Other simple contracts have worked and I am able to send transactions on Rinkeby properly, so assume this is due to the added complexity of using the Uniswap API, etc.</p>