尝试创建新的 Uniswap V3 位置时出错

问题描述 投票:0回答:1

我一直在尝试使用 Hardhat 和 Arbitrum 主网分叉创建新仓位,但是当调用 NonfungiblePositionManager.mint() 时,交易将被还原:

Error: Transaction reverted without a reason string

我可能做错了什么,因为这是我第一次使用分叉功能并且使用 Uniswap V3 环境。

我认为错误可能出在 WETH 上,所以我尝试使用 USDC/DAI 池,但仍然遇到相同的错误。

我从 Uniswap V3 官方docs

获取了示例合约

这是我的智能合约

contract Ranger is IERC721Receiver {
    address public constant WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
    address public constant USDC = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831;

    uint24 public constant poolFee = 500;

    INonfungiblePositionManager public constant nonfungiblePositionManager =
        INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);

    struct Deposit {
        address owner;
        uint128 liquidity;
        address token0;
        address token1;
    }

    mapping(uint256 => Deposit) public deposits;

    function onERC721Received(
        address operator,
        address,
        uint256 tokenId,
        bytes calldata
    ) external override returns (bytes4) {
        _createDeposit(operator, tokenId);
        return this.onERC721Received.selector;
    }

    function _createDeposit(address owner, uint256 tokenId) internal {
        (
            ,
            ,
            address token0,
            address token1,
            ,
            ,
            ,
            uint128 liquidity,
            ,
            ,
            ,

        ) = nonfungiblePositionManager.positions(tokenId);
        deposits[tokenId] = Deposit({
            owner: owner,
            liquidity: liquidity,
            token0: token0,
            token1: token1
        });

        console.log("Token ID: ", tokenId);
        console.log("Liquidity: ", liquidity);
    }

    function mintNewPosition(
        uint256 amount0ToMint,
        uint256 amount1ToMint
    )
        external
        returns (
            uint256 tokenId,
            uint128 liquidity,
            uint256 amount0,
            uint256 amount1
        )
    {
        TransferHelper.safeApprove(
            USDC,
            address(nonfungiblePositionManager),
            amount0ToMint
        );
        TransferHelper.safeApprove(
            WETH,
            address(nonfungiblePositionManager),
            amount1ToMint
        );
        INonfungiblePositionManager.MintParams
            memory params = INonfungiblePositionManager.MintParams({
                token0: USDC,
                token1: WETH,
                fee: poolFee,
                tickLower: TickMath.MIN_TICK,
                tickUpper: TickMath.MAX_TICK,
                amount0Desired: amount0ToMint,
                amount1Desired: amount1ToMint,
                amount0Min: 0,
                amount1Min: 0,
                recipient: address(this),
                deadline: block.timestamp
            });

        (tokenId, liquidity, amount0, amount1) = nonfungiblePositionManager
            .mint(params);

        _createDeposit(msg.sender, tokenId);

        if (amount1 < amount1ToMint) {
            TransferHelper.safeApprove(
                USDC,
                address(nonfungiblePositionManager),
                0
            );
            uint256 refund1 = amount1ToMint - amount1;
            TransferHelper.safeTransfer(USDC, msg.sender, refund1);
        }
        if (amount0 < amount0ToMint) {
            TransferHelper.safeApprove(
                WETH,
                address(nonfungiblePositionManager),
                0
            );
            uint256 refund0 = amount0ToMint - amount0;
            TransferHelper.safeTransfer(WETH, msg.sender, refund0);
        }
    }
}

这是我的安全帽测试文件

const WETH = "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1";
const USDC = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831";

const FEE = 500;

const WHALE = "0x090ee598777CaDDAd04Df4271B167F38E73a9Bf0";

const AMOUNT0 = 10000n;
const AMOUNT1 = 10n;

describe("Ranger", async () => {
  let contract: Contract;
  let accounts: HardhatEthersSigner[];
  let weth: IERC20;
  let usdc: IERC20;
  //   let dai: IERC20;

  before(async () => {
    await deployments.fixture(["all"]);

    accounts = await ethers.getSigners();

    const tmp = await deployments.get("Ranger");
    contract = await ethers.getContractAt(tmp.abi, tmp.address);

    usdc = await ethers.getContractAt("IERC20", USDC);
    weth = await ethers.getContractAt("IERC20", WETH);

    await network.provider.request({
      method: "hardhat_impersonateAccount",
      params: [WHALE],
    });

    const whale = await ethers.getSigner(WHALE);

    const token0amount = AMOUNT0 * 10n ** 6n;
    const token1amount = AMOUNT1 * 10n ** 18n;

    expect(await usdc.balanceOf(whale.address)).to.gte(token0amount);
    expect(await weth.balanceOf(whale.address)).to.gte(token1amount);

    await usdc.connect(whale).transfer(accounts[0].address, token0amount);
    await weth.connect(whale).transfer(accounts[0].address, token1amount);
  });

  it("Pool with given parameters exist", async () => {
    const factory = await ethers.getContractAt(
      "IUniswapV3Factory",
      "0x1F98431c8aD98523631AE4a59f267346ea31F984"
    );

    const pool = await factory.getPool(USDC, WETH, FEE);
    expect(pool).to.not.equal("0x0000000000000000000000000000000000000000");
  });

  it("Mint new position", async () => {
    const token0amount = AMOUNT0 * 10n ** 6n;
    const token1amount = AMOUNT1 * 10n ** 18n;

    const contractAddress = await contract.getAddress();

    await usdc.connect(accounts[0]).transfer(contractAddress, token0amount);
    await weth.connect(accounts[0]).transfer(contractAddress, token1amount);

    expect(await usdc.balanceOf(contractAddress)).to.gte(token0amount);
    expect(await weth.balanceOf(contractAddress)).to.gte(token1amount);

    await contract.mintNewPosition(token0amount, token1amount);
  });
});

这是我的安全帽测试输出:

  Ranger
    ✔ Pool with given parameters exist (578ms)
    1) Mint new position


  1 passing (7s)
  1 failing

  1) Ranger
       Mint new position:
     Error: Transaction reverted without a reason string
    at <UnrecognizedContract>.<unknown> (0xc36442b4a4522e871399cd717abdd847ab11fe88)
    at Ranger.mintNewPosition (contracts/Ranger.sol:132)
    at EdrProviderWrapper.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:429:41)
    at async HardhatEthersSigner.sendTransaction (node_modules/@nomicfoundation/hardhat-ethers/src/signers.ts:125:18)
    at async send (node_modules/ethers/src.ts/contract/contract.ts:313:20)
    at async Proxy.mintNewPosition (node_modules/ethers/src.ts/contract/contract.ts:352:16)
    at async Context.<anonymous> (test/ranger.test.ts:84:5)

感谢您的帮助和时间,如果您需要任何其他信息,请告诉我。

亲切的问候, 朱利安

ethereum solidity hardhat
1个回答
0
投票

您的代码和逻辑似乎是正确的。但是,错误“事务在没有原因字符串的情况下恢复”通常意味着事务已失败,但恢复操作不包含特定的错误消息。简单来说,solidity evm 并没有弄清楚发生了什么。

我检查了这些地址:

const WETH = "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1";
const USDC = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831";
        
INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);

它们都是

Goerli TestNet
上的有效地址。但鲸鱼账户不是

const WHALE = "0x090ee598777CaDDAd04Df4271B167F38E73a9Bf0";

在您的测试设置中,您正在冒充鲸鱼帐户:

await network.provider.request({
      method: "hardhat_impersonateAccount",
      params: [WHALE],
    });

按照你的逻辑,

whale
账户必须持有大量的
USDC
WETH
,但它根本不存在:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.