繁体   English   中英

收到错误:交换时出现错误“STF”UniswapV3 失败

[英]getting error: Fail with error 'STF' UniswapV3 on swap

创建了一个在孟买 BC 上部署的基本合同。

同一个 uni 交换基本的,只是地址不同。 因为这是在不列颠哥伦比亚省的孟买,所以我用 wmatic 创建了它。

然后在批准所有地址后,我得到这个错误,没有任何解释或选项来理解当我尝试单次交换时失败的地方。

 // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; pragma abicoder v2; import "hardhat/console.sol"; import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol'; import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol'; contract SwapExamples { // 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; address public constant WMATIC = 0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889; address public constant WETH = 0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa; // 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 WMATIC for a maximum possible amount of WETH /// using the WMATIC/WETH 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 WMATIC for this function to succeed. /// @param amountIn The exact amount of WMATIC that will be swapped for WETH. /// @return amountOut The amount of WETH received. function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) { // msg.sender must approve this contract // Transfer the specified amount of WMATIC to this contract. TransferHelper.safeTransferFrom(WMATIC, msg.sender, address(this), amountIn); // Approve the router to spend WMATIC. TransferHelper.safeApprove(WMATIC, 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: WMATIC, tokenOut: WETH, 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 WMATIC for a fixed amount of WETH. /// @dev The calling address must approve this contract to spend its WMATIC for this function to succeed. As the amount of input WMATIC is variable, /// the calling address will need to approve for a slightly higher amount, anticipating some variance. /// @param amountOut The exact amount of WETH to receive from the swap. /// @param amountInMaximum The amount of WMATIC we are willing to spend to receive the specified amount of WETH. /// @return amountIn The amount of WMATIC actually spent in the swap. function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) { // Transfer the specified amount of WMATIC to this contract. TransferHelper.safeTransferFrom(WMATIC, msg.sender, address(this), amountInMaximum); // Approve the router to spend the specifed `amountInMaximum` of WMATIC. // In production, you should choose the maximum amount to spend based on oracles or other data sources to acheive a better swap. TransferHelper.safeApprove(WMATIC, address(swapRouter), amountInMaximum); ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({ tokenIn: WMATIC, tokenOut: WETH, 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 < amountInMaximum) { TransferHelper.safeApprove(WMATIC, address(swapRouter), 0); TransferHelper.safeTransfer(WMATIC, msg.sender, amountInMaximum - amountIn); } } }

两周以来我和你处于同样的状态。 我还没有解决问题,但我有更多对你有用的数据:

我尝试在 mumbai.network 上的https://app.uniswap.org上进行交换,我发现孟买的 SwapRouter 地址可能是错误的或者不是 uniswap 官方网站上的主要地址(我的意思是:0xE592427A0AEce92De3Edee1F18E0157C05861564) .

我不知道他们是否使用了两个地址,但我尝试了两次,两次都通过了 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 作为 SwapRouter。 如果您尝试在网站上进行交换,您可以检查它。

我的交易示例: https://mumbai.polygonscan.com/tx/0xa7e75b78ec8f5ae311d0252d0ad7412176ebe7f063df72a8f2c347543f8f2103

好的,终于在几天后我实现了在孟买与 exactInputSingle 的交换。 此测试将 0.5Wmatic 换成 weth:我附上我的脚本:

TestSwap.sol

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';

import "./SwapRouter02lib/ISwapRouter02.sol";
import "./SwapRouter02lib/IV3SwapRouter.sol";
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

contract TestSwap {
    using LowGasSafeMath for uint256;

    ISwapRouter02 public immutable uniswapRouter;

    constructor(address _uniswapRouter) {
        uniswapRouter = ISwapRouter02(_uniswapRouter);
    }

    function swapUniswap(
        address token0, 
        address token1, 
        uint256 amount, 
        uint256 fee 
    ) external returns (uint256 amountOut) {
        require(IERC20(token0).transferFrom(msg.sender, address(this), amount),"STF v2");
        require(IERC20(token0).approve(address(uniswapRouter), amount),"SA v2");

        uint256 amountMin = LowGasSafeMath.add(amount, fee);
        IV3SwapRouter.ExactInputSingleParams memory params = IV3SwapRouter.ExactInputSingleParams({
            tokenIn: token0,
            tokenOut: token1,
            fee: uint24(fee),
            recipient: msg.sender,
            amountIn: amount,
            amountOutMinimum: 0,
            sqrtPriceLimitX96: 0
        });

        (bool success, bytes memory amountBytes) = address(uniswapRouter).call(
            abi.encodeWithSelector(
                IV3SwapRouter.exactInputSingle.selector,
                params
            )
        );

        return bytesToUint(amountBytes);
    }

    function bytesToUint(bytes memory _bytes) internal pure returns (uint256 value) {
        assembly {
            value := mload(add(_bytes, 0x20))
        }
    }
}

部署-test.js

const hre = require('hardhat');
const ethers = hre.ethers;
const { abi: abiERC20 } = require("../artifacts/contracts/IERC20.sol/IERC20.json");
const uniswapRouter = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"; //ROUTER 02
const uniswapFactory = "0x1F98431c8aD98523631AE4a59f267346ea31F984"; //FACTORY

const wmatic = "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889"; //wmatic mumbai
const weth = "0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa"; //weth mumbai

const fee1 = 500;

const signerAddress = "0x1234567890123456789012345678901234567890";//this must be one of your address with wmatic tokens (I tested on mumbai)

async function main() {
    
    await hre.network.provider.request({
        method: 'hardhat_impersonateAccount',
        params: [signerAddress],
      });
      const signer = await ethers.provider.getSigner(signerAddress);

    var wmaticContract = new ethers.Contract(
        wmatic,
        abiERC20,
        signer
    );

    var wethContract = new ethers.Contract(
        weth,
        abiERC20,
        signer
    );

    const TestSwap = await ethers.getContractFactory("TestSwap");
    const testSwap = await TestSwap.deploy(
        uniswapRouter
    );
    await testSwap.deployed();

    console.log((await wmaticContract.balanceOf(signer._address)).toString());
    console.log((await wethContract.balanceOf(signer._address)).toString());

    console.log((await wmaticContract.balanceOf(testSwap.address)).toString());
    console.log((await wethContract.balanceOf(testSwap.address)).toString());

    const amountApprove = ethers.utils.parseEther('1'); 
    const amount = ethers.utils.parseEther('0.5');

    const GAS_PARAMS =  {
        gasLimit: "1250000",//exagerate amount of gas, must be adjusted
        gasPrice: ethers.utils.parseUnits('100','gwei').toString(),
    };
    const txApproveWMatic = await wmaticContract.connect(signer).approve(
        testSwap.address, 
        amountApprove, 
        GAS_PARAMS);
    await txApproveWMatic.wait();

    const tx = await testSwap.connect(signer).swapUniswap(
        wmatic,
        weth,
        amount,
        fee1, 
        GAS_PARAMS
    );

    console.log(tx);
    const txResponse = await tx.wait();
    console.log(txResponse);

    console.log((await wmaticContract.balanceOf(signer._address)).toString());
    console.log((await wethContract.balanceOf(signer._address)).toString());
    console.log((await wmaticContract.balanceOf(testSwap.address)).toString());
    console.log((await wethContract.balanceOf(testSwap.address)).toString());
}

main();

运行它:

 $ npx hardhat run scripts/deploy-test.js

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM