Dmitry Zakharov
Posted on September 23, 2023
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});
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.
Posted on September 23, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.