Uniswap V3 PoolAddress.computeAddress
computes different address comparing to the one I get from UniswapV3poolFactory.getPool
. And in my code it is ok, I can get pool address from this mapping, but uniswap contracts uses PoolAddress
library in order to get pool address.
When I try to mint new position using mint
function from NonfungiblePositionManager.sol
this function calls addLiquidity
from LiquidityManagement.sol
and this function has call to the PoolAddress.sol
library method computeAddress
. And there it throws because after computing pool
address it tries to call methods from pool
but it can't cause address is wrong.
I've tried to change the order of the tokens that I pass to the mint
function but the order is correct, I've also logged all of the data that is related to pool address computation in uniswap contracts using hardhat local chain and it is the same to the one I used for getPool
mapping. The only thing that still can cause wrong computations on my opinion is the POOL_INIT_CODE_HASH
constant in PoolAddress
library, but I haven't changed that. All mentioned methods I'll post below the text along with links to uniswap repos. Compiler version that I've used for all unsiwap contracts is 0.7.6
. If anyone got any idea how to solve this, please, let me know.
NonfungiblePositionManager.sol
NonfungiblePositionManager.sol
function mint(MintParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
)
{
IUniswapV3Pool pool;
// it throws
---> (liquidity, amount0, amount1, pool) = addLiquidity(
AddLiquidityParams({
token0: params.token0,
token1: params.token1,
fee: params.fee,
recipient: address(this),
tickLower: params.tickLower,
tickUpper: params.tickUpper,
amount0Desired: params.amount0Desired,
amount1Desired: params.amount1Desired,
amount0Min: params.amount0Min,
amount1Min: params.amount1Min
})
);
_mint(params.recipient, (tokenId = _nextId++));
bytes32 positionKey = PositionKey.compute(address(this), params.tickLower, params.tickUpper);
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
// idempotent set
uint80 poolId = cachePoolKey(
address(pool),
PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee})
);
_positions[tokenId] = Position({
nonce: 0,
operator: address(0),
poolId: poolId,
tickLower: params.tickLower,
tickUpper: params.tickUpper,
liquidity: liquidity,
feeGrowthInside0LastX128: feeGrowthInside0LastX128,
feeGrowthInside1LastX128: feeGrowthInside1LastX128,
tokensOwed0: 0,
tokensOwed1: 0
});
emit IncreaseLiquidity(tokenId, liquidity, amount0, amount1);
}
LiquidityManagement.sol
function addLiquidity(AddLiquidityParams memory params)
internal
returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1,
IUniswapV3Pool pool
)
{
PoolAddress.PoolKey memory poolKey = PoolAddress.PoolKey({
token0: params.token0,
token1: params.token1,
fee: params.fee
});
// here is the computation of pool address
---> pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
// all subsequent operations fails
// compute the liquidity amount
{
(uint160 sqrtPriceX96, , , , , , ) = pool.slot0();
console.log("liquidity 4");
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);
console.log("liquidity 5");
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);
console.log("liquidity 6");
liquidity = LiquidityAmounts.getLiquidityForAmounts(
sqrtPriceX96,
sqrtRatioAX96,
sqrtRatioBX96,
params.amount0Desired,
params.amount1Desired
);
console.log("liquidity 7");
}
(amount0, amount1) = pool.mint(
params.recipient,
params.tickLower,
params.tickUpper,
liquidity,
abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))
);
require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, "Price slippage check");
}
PoolAddress.sol
bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
function computeAddress(address factory, PoolKey memory key) internal view returns (address pool) {
require(key.token0 < key.token1);
pool = address(
// uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encode(key.token0, key.token1, key.fee)),
POOL_INIT_CODE_HASH
)
)
)
// )
);
}
You will need to change the init hash code
https://docs.uniswap.org/protocol/V2/guides/smart-contract-integration/quick-start#writing-tests