H.Li
H.Li

Reputation: 361

Uniswap v3 nonfungiblePositionManager.mint revert after createAndInitializePoolIfNecessary

I use the official deploy tool "successfully" to deploy Uniswap v3 to a EVM comparable testnet. After NonfungiblePositionManager.createAndInitializePoolIfNecessary(), I call NonfungiblePositionManager.mint() to mint a new position but it always reverts. Here is the input I used:

 console.log("creating pool...");
   await NFPositionManagerInstance.createAndInitializePoolIfNecessary(
     DaiTokenInstance.address,
     USDTTokenInstance.address,
     3000,
     "80000000000000000000000000000"
   ); // this can be successfully triggered

   console.log("minting a position...")
   let tx = await NFPositionManagerInstance.mint({
      token0: DaiTokenInstance.address,
      token1: USDTTokenInstance.address,
      fee: 3000,
      tickLower: 193,
      tickUpper: 194,
      amount0Desired: 1000,
      amount1Desired: 1000,
      amount0Min: 0,
      amount1Min: 0, 
      recipient: "0x668417616f1502D13EA1f9528F83072A133e8E01",
      deadline: Math.round(+new Date()/1000 + 20)
   }); // this always revert

Anyone know what is going on? I plan to debug this deeply in the contract next.

Upvotes: 0

Views: 2786

Answers (4)

Anton Gulak
Anton Gulak

Reputation: 1

Check also the token order

function compareAddresses(addr1: string, addr2: string): boolean {
  return addr1.toLowerCase() > addr2.toLowerCase();
}

in the library PoolAddress there is require with empty error

require(key.token0 < key.token1)

Upvotes: 0

silvercondor
silvercondor

Reputation: 139

I ran into this issue and it's annoying that this isn't documented. My solution is to force the set tick to always be divisible by the tick spacing

let tickUpper=1234;
let tickLower=-1234;

// We get the tick spacing
let tickSpacing=await deployedPairContract.tickSpacing();

// We force the tick spacing to always be divisible
tickLower=tickLower<0?-(Math.floor(-tickLower/tickSpacing)*tickSpacing):Math.floor(tickLower/tickSpacing)*tickSpacing;
tickUpper=tickUpper<0?-(Math.floor(-tickUpper/tickSpacing)*tickSpacing):Math.floor(tickUpper/tickSpacing)*tickSpacing;            

//... continue with rest of params

In case you are facing the issue in your contract, similar math can be applied

int24 tickLower = -887272;
int24 tickUpper = -tickLower;

tickLower=tickLower<0?-(-tickLower/tickSpacing*tickSpacing):tickLower/tickSpacing*tickSpacing;

tickUpper=tickUpper<0?-(-tickUpper/tickSpacing*tickSpacing):tickUpper/tickSpacing*tickSpacing;

Upvotes: 1

tsknakamura
tsknakamura

Reputation: 193

I ran simulation on tenderly.co Changing ticks to numbers divisible by the tickSpacig fixed it.

tenderly simulation

Upvotes: 3

Zack Scott
Zack Scott

Reputation: 21

I was having the same issue. There are a few things that could be the issue, but I would first take a look at the code here https://github.com/zack53/uniswapv3-pool-deploy/blob/main/src/test/TERC20.js that I have working. The issue I was having was specifically with the tickLower and tickUpper due to getting a revert without reason error. I essentially had to get the current tick from slot0 of the deployed pair, and then, I also grabbed the tickSpacing from the deployed pair. Once I had those, I used them to calculate a tick spacing that allowed me to mint a position. The deployed pair is a pair that I deployed myself. Both of the tokens are 18 decimals. A snippet of my code is below that works:

    // Get tick and tick spacing
    let slot0 = await deployedPairContract.methods.slot0().call()
    let tickSpacing = parseInt(await deployedPairContract.methods.tickSpacing().call())
    // Get correct token order for deployed contract pair
    let token0 = await deployedPairContract.methods.token0().call()
    let token1 = await deployedPairContract.methods.token1().call()
    // Params needed for mint
    let params = {
      token0: token0,
      token1: token1,
      fee: pairFee,
      tickLower: parseInt(slot0.tick) - tickSpacing * 2,
      tickUpper: parseInt(slot0.tick) + tickSpacing * 2,
      amount0Desired: 10,
      amount1Desired: 10,
      amount0Min: 0,
      amount1Min: 0,
      recipient: accounts[0],
      deadline: 5000000000
    }
    await t1ERC20Contract.approve(UniSwapV3NPositionManagerAddress, BigNumber(1000).shiftedBy(decimals).toFixed(0), { from: accounts[0] })
    await t2ERC20Contract.approve(UniSwapV3NPositionManagerAddress, BigNumber(1000).shiftedBy(decimals).toFixed(0), { from: accounts[0] })
    await uniswapV3NPositionManager.methods.mint(params).send({ from: accounts[0] })

Upvotes: 1

Related Questions