Uniswap / v3-sdk

šŸ›  An SDK for building applications on top of Uniswap V3
MIT License
544 stars 416 forks source link

While adding liquidity to the pool uniswapv3-sdk gives the following error reverted with reason string 'LOK' #177

Open Hareem-Saad opened 1 year ago

Hareem-Saad commented 1 year ago

Packages & Versions

"devDependencies": {
    "@nomicfoundation/hardhat-toolbox": "^2.0.2",
    "hardhat": "^2.16.0"
  },
  "dependencies": {
    "@openzeppelin/contracts": "^4.9.2",
    "@uniswap/v3-sdk": "^3.8.3",
    "dotenv": "^16.3.1"
  }

Code

I am forking polygon mainnet on hardhat then running it locally, The pool created is betweem USDC and TokenA (a token i created)

const hre = require("hardhat");
const { ethers } = hre;
const {
  Pool,
  TickMath,
  nearestUsableTick,
  TICK_SPACINGS,
} = require("@uniswap/v3-sdk");
const {
  abi: poolAbi,
} = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json");
const {
  abi: factoryAbi,
} = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json");
const {
  abi: routerAbi,
} = require("@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json");
const { abi: NonfungiblePositionManagerAbi } = require('@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json');

const { abi: usdcAbi } = require("./../contracts/abi/udsc.json");
const { abi: wmaticAbi } = require("./../contracts/abi/WMATIC.json");
const { abi: TokenAAbi } = require("./../contracts/abi/TokenA.json");
const dotenv = require("dotenv");
dotenv.config();

async function main() {

  // get signer
  const [signer] = await ethers.getSigners();

  // deploy tokenA
  //...
  await tokenA.deployed();

  // all addresses
  //...
  const provider = new ethers.providers.JsonRpcProvider(
    process.env.POLYGON_RPC_URL
  );

  // all connections
  //...

  /// STEP 1: GET USDC
  //...

  /// STEP 1: CREATE POOL

  const fee = 3000; // Fee in hundredths of a percent (e.g., 3000 is 3%)
  const tickSpacing = TICK_SPACINGS[fee];
  const initialSqrtPrice = TickMath.getSqrtRatioAtTick(0); // Set the initial price ratio
  const initialTick = nearestUsableTick(-887272, tickSpacing); // Set the initial tick

  console.log(0);

  // approve router contract to usdc
  const result = await usdc
    .connect(signer)
    .approve(routerAddress, ethers.constants.MaxUint256, {
      gasLimit: 30000000,
    });
  console.log("RESULT ::: ", result);
  //   await TokenA.approve(routerAddress, ethers.constants.MaxUint256);

  console.log(1);

  const createPoolTx = await factory
    .connect(signer)
    .createPool(USDC, TokenA.address, fee);
  console.log(2);
  const createPoolReceipt = await createPoolTx.wait();
  console.log(3);
  const poolAddress = createPoolReceipt.events[0].args.pool;
  console.log(4, poolAddress);
  const pool = new ethers.Contract(poolAddress, poolAbi);
  console.log(5);
  // const initializeTx = await pool.connect(signer).initialize(initialSqrtPrice, {gasLimit: 30000000});
  // console.log(6);
  // await initializeTx.wait();
  // console.log(7);
  console.log(createPoolReceipt, poolAddress);

  /// STEP 2: ADD LIQUIDITY

  // Define the amounts of tokens to add
  const amountUSDCDesired = ethers.utils.parseUnits('10000000000000000000000', 6); // 10,000 USDC
  const amountTokenADesired = ethers.utils.parseEther('10000000000000000000000', 18); // 10000 TokenA

  // tickLower = floor(log(0.99) / log(1.0001)) = -202
  // tickUpper = floor(log(1.01) / log(1.0001)) = 200
  // Define the range position
  const tickLower = -202;
  const tickUpper = 200;

  console.log(6);
  const approveUSDC = await usdc.connect(signer).approve(positionManager.address, amountUSDCDesired);
  console.log(7);
  const approveTokenA = await TokenA.connect(signer).approve(positionManager.address, amountTokenADesired);
  console.log(8);

  await approveUSDC.wait();
  await approveTokenA.wait();

   // ERROR
  // Add liquidity
  const tx = await positionManager.connect(signer).mint([
    USDC,
    TokenA.address,
    fee,
    tickLower,
    tickUpper,
    amountUSDCDesired,
    amountTokenADesired,
    0,
    0,
    signer.address,
    Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from the current Unix time
  ]);
  console.log(11);

  await tx.wait();

  console.log('Liquidity added');
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

On await positionManager.connect(signer).mint it fails with the string LOK, which I cannot understand because there are no more calls calling to the pool, its just this code which executes line after line.

This error could be linked to this issue. When creating the pool, the pool gets created without any issue but I have to then close the node running the polygon mainnet fork to execute the same script again also the code does not initialize the pool (hence it is commented out)

ford152 commented 6 months ago

I was having this issue on both Polygon and Mumbai. I created a new pool and then was getting the LOK error trying to mint the first LP position. I ended up resolving it by calling initialize() on the UniswapV3Pool contract. so in this order: -create new pool -initialize the pool -mint new position using NonfungiblePositionManager