Forem

Dmitry Zakharov
Dmitry Zakharov

Posted on

25 1

How to Add a New Pool to Uniswap V3

Intro

Many existing projects use the third version of a well-known Uniswap protocol as Oracle to get the current price for many assets. Uniswap V3 can also be used in one of the strategies like yearn or harvest strategies as a pool of liquidity, which can create profits for your deposit through time. Some projects also add integration with Uniswap V3 to increase user experience and make users' lives a little bit easier. In all of these scenarios, it is crucial to check how the poisoned pool, which can be added by a hacker to uniswap can affect the protocol. To check this scenario, we create a test in the hardhat environment.

Adding liquidity pool to UniswapV3

The code snippet in the hardhat testing environment is presented below. All necessary notes to the code are given as well.

const tokenFactory = await ethers.getContractFactory("EvilToken");
const evilToken = await tokenFactory.connect(deployer).deploy();
const positionManager = await ethers.getContractAt('INonfungiblePositionManager', "0xC36442b4a4522E871399CD717aBDD847Ab11FE88");
const WETH = await ethers.getContractAt('IWETH', addresses.tokens.WETH);
// call approve for tokens before adding a new pool
call approveawait WETH.connect(deployer).approve(positionManager.address, ethers.utils.parseEther('0.1'), {gasPrice: 0});
await evilToken.connect(deployer).approve(positionManager.address, ethers.utils.parseEther('100'), {gasPrice: 0});
let multiCallParams = [
// first call
"0x13ead562" + // encoded function signature ( createAndInitializePoolIfNecessary(address, address, uint24, uint160) )
"000000000000000000000000" + evilToken.address.toLowerCase().substring(2) + // token1 address
"000000000000000000000000" +  WETH.address.toLowerCase().substring(2) + // token2 address
"00000000000000000000000000000000000000000000000000000000000001f4" + // fee
"000000000000000000000000000000000000000005b96aabfac7cdc4b3b58fc2", // sqrtPriceX96
// second call
"0x88316456" + // encoded function signature ( mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256)) )
"000000000000000000000000" + evilToken.address.toLowerCase().substring(2) + // token1 address
"000000000000000000000000" +  WETH.address.toLowerCase().substring(2) + // token2 address
"00000000000000000000000000000000000000000000000000000000000001f4" + // fee
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89f0e" + // tick lower
"0000000000000000000000000000000000000000000000000000000000010dd8" + // tick upper
"00000000000000000000000000000000000000000000000ad5a4b6712c4647c3" + // amount 1 desired
"000000000000000000000000000000000000000000000000016345785d8a0000" + // amount 2 desired
"00000000000000000000000000000000000000000000000acebaf563cd50439c" + // min amount 1 expected
"000000000000000000000000000000000000000000000000016261cfc3291456" + // min amount 2 expected 
"000000000000000000000000" + signer3.address.toLowerCase().substring(2) + // deployer address "00000000000000000000000000000000000000000000000000000000610bb8b6" // deadline
];
// adding a new liquidity pool through the position manager
await positionManager.connect(deployer).multicall(multiCallParams, {gasPrice: 0});
Enter fullscreen mode Exit fullscreen mode

In this test, EvilToken is a standard ERC20 token that can be minted or burned by the deployer, positionManager is one of Uniswap V3 ecosystem's smart contracts which gives access to adding new pools of liquidity, WETH is a token representing wrapped ether. multiCallParams is an array of bytes which contains all necessary parameters to deploy a new liquidity pool. It is worth saying that some of the parameters used in multiCallParams cannot be easily calculated, like sqrtPriceX96 or tick_lower. To calculate these parameters, you can use a Uniswap V3 dApp in the ropsten network. It is very easy to calculate these parameters through dApp. First, you create a new liquidity pool in dApp with parameters that you want to use, and then you just decompile your transaction in ropsten etherscan and get values of the necessary parameters in byte representation.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay