Uniswap V3PoolAddress.computeAddress
计算的地址与我从UniswapV3poolFactory.getPool
获得的地址不同。在我的代码中,我可以从这个映射中获取池地址,但uniswap合约使用PoolAddress
库来获取池地址。
当我尝试使用NonfungiblePositionManager.sol
中的mint
函数创建新位置时,该函数从LiquidityManagement.sol
调用addLiquidity
,并且该函数具有对PoolAddress.sol
库方法computeAddress
的调用。它之所以抛出,是因为在计算pool
地址后,它试图从pool
调用方法,但不会导致地址错误。
我试图更改传递给mint
函数的令牌的顺序,但顺序是正确的,我还使用hardhat本地链记录了uniswap契约中与池地址计算相关的所有数据,这与我用于getPool
映射的数据相同。在我看来,唯一可能导致错误计算的是PoolAddress
库中的POOL_INIT_CODE_HASH
常数,但我没有改变这一点。我将在文本下面发布所有提到的方法,以及uniswap转发的链接。我为所有unswap合约使用的编译器版本是0.7.6
。如果有人知道如何解决这个问题,请告诉我。
v3核心
v3外围
不可执行的位置管理器.sol
流动性管理.sol
PoolAddress.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
)
)
)
// )
);
}
您需要更改init哈希代码
https://docs.uniswap.org/protocol/V2/guides/smart-contract-integration/quick-start#writing-测试
https://ethereum.stackexchange.com/questions/89680/what-is-init-code-hash-and-how-is-it-calculated-used-in-defi-smart-contracts