来自 Uniswap V3 的简单 swapExactInputSingle 在 Rinkeby 上失败

Simple swapExactInputSingle from Uniswap V3 fails on Rinkeby

我已经尝试按照 Uniswaps guide 实现简单的 swapExactInputSingle 功能并在 Rinkeby 上部署了合约。

代码:

contract Swap {
    using LowGasSafeMath for uint256;

    address private constant SWAP_ROUTER =
        0xE592427A0AEce92De3Edee1F18E0157C05861564;
    address private constant WETH = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
    address public constant DAI = 0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735;

    address public immutable _owner;
    ISwapRouter public immutable swapRouter;

    constructor() {
        _owner = msg.sender;
        swapRouter = ISwapRouter(SWAP_ROUTER);
    }

    function swapExactInputSingle(uint256 amountIn)
        external
        returns (uint256 amountOut)
    {
        //Transfer DAI here, and approve its usage for router
        TransferHelper.safeTransferFrom(
            DAI,
            msg.sender,
            address(this),
            amountIn
        );
        TransferHelper.safeApprove(DAI, address(swapRouter), amountIn);

        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
            .ExactInputSingleParams({
                tokenIn: DAI,
                tokenOut: WETH,
                fee: 3000,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0
            });

        amountOut = swapRouter.exactInputSingle(params);
    }

    receive() external payable {}
}

DAI 和 WETH 地址对于 Rinkeby 网络来说似乎是正确的。我已经尝试了两个 Uniswap SwapRouters 地址(我不确定我应该使用哪个:SwapRoutertheir doc 中的 SwapRouter02),更改它们不会影响结果。部署合约后,当我尝试使用 MetaMask 通过 etherscan 与其交互时,在确认交易之前在元掩码中我收到警告:

This transaction is expected to fail. Trying to execute it is expected to be expensive but fail, and is not recommended.

确认这笔交易后花了很长时间,最终确实失败了。

我做错了什么?我的钱包里确实有正确的 DAI

另外,为什么 MetaMask 对我的交易建议 gas limit 28472169 而当我与 Uniswap V3 界面交互时,对于相同的交换它只建议 129129 ?

确保你批准你的合同,从你的钱包中花费你的 dai

//Transfer DAI here, and approve its usage for router
    TransferHelper.safeTransferFrom(
        DAI,
        msg.sender,
        address(this),
        amountIn
    );

此函数将 dai 从您的钱包转移到您的合约 它需要批准 手动批准你的合约,通过它的合约或 abi 在你的钱包中花费 dai https://rinkeby.etherscan.io/address/0xc7ad46e0b8a400bb3c915120d284aafba8fc4735#writeContract

原来我们有 2 个不同的问题。

第一个,就是@Crypto_Rachel提到的那个东西。合同内部的批准只是两个需要的批准之一。在交易之前,我们还需要手动批准我们的合约以从我们的钱包中获取代币 (DAI)。

正如我在问题中提到的,我一直在尝试两种不同的交换路由器: SwapRouterSwapRouter02。第一个问题解决后,我一直只使用 SwapRouter02.

进行测试

事实证明,SwapRouter02 使用了不同的 ExactInputSingleParams 结构。它没有 delay 参数。使用 import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol" 及其提供的结构,我应该使用 SwapRouter。切换到该路由器解决了一个问题并使我的交易通过。

如果您想详细了解该内容,请查看此博文: https://brightinventions.pl/blog/single-swap-on-uniswap-v3-with-3-common-mistakes