While adding liquidity to the pool uniswapv3-sdk gives the following error reverted with reason string 'LOK'
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)
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