计算uniswap v3交易池子地址
Tx
https://etherscan.io/address/0x840deeef2f115cf50da625f7368c24af6fe74410#readContract
描述
使用Java链下计算v3 pool地址,不需要调用工厂合约查询pool地址
Java代码
package com.hlf.eth;
import org.spongycastle.util.encoders.Hex;
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Bytes1;
import org.web3j.abi.datatypes.generated.Bytes32;
import org.web3j.abi.datatypes.generated.Uint24;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Hash;
import org.web3j.utils.Numeric;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: CalculatPoolAddress
* @Author: huanglefei
* @CreateDate: 2023/8/18 22:04
* @Description: 计算uniswap v3的池子地址
* @Version: 1.0
* /// @notice Deterministically computes the pool address given the factory and PoolKey
* /// @param factory The Uniswap V3 factory contract address
* /// @param key The PoolKey
* /// @return pool The contract address of the V3 pool
* function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
* require(key.token0 < key.token1);
* pool = address(
* uint256(
* keccak256(
* abi.encodePacked(
* hex'ff',
* factory,
* keccak256(abi.encode(key.token0, key.token1, key.fee)),
* POOL_INIT_CODE_HASH
* )
* )
* )
* );
* }
**/
public class CalculatPoolAddress {
public static void main(String[] args) {
// UniswapV3
// https://etherscan.io/address/0x840deeef2f115cf50da625f7368c24af6fe74410#readContract
String poolInitCodeHash = "0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54";
String factory = "0x1F98431c8aD98523631AE4a59f267346ea31F984";
String tokenA = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
String tokenB = "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704";
BigInteger fee = BigInteger.valueOf(500);
String pool = getPoolAddress(poolInitCodeHash, factory, tokenA, tokenB, fee);
System.out.println("交易池地址:" + pool);
}
public static String getPoolAddress(String poolInitCodeHash, String factory, String tokenA, String tokenB, BigInteger fee) {
List<String> strings = sortTokens(tokenA, tokenB);
tokenA = strings.get(0);
tokenB = strings.get(1);
Bytes1 parff = new Bytes1(Numeric.hexStringToByteArray("ff"));
Bytes32 parInitCodeHash = new Bytes32(Numeric.hexStringToByteArray(poolInitCodeHash));
String encodeFee = TypeEncoder.encode(new Uint24(fee));
String encodeTokenA = TypeEncoder.encode(new Address(tokenA));
StringBuilder tokenAddress = new StringBuilder();
tokenAddress.append(encodeTokenA);
tokenAddress.append(TypeEncoder.encode(new Address(tokenB)));
tokenAddress.append(encodeFee);
String tokenHash = Hash.sha3("0x" + tokenAddress.toString());
StringBuilder msg = new StringBuilder();
msg.append(Hex.toHexString(parff.getValue()));
msg.append(factory.substring(2, factory.length()));
msg.append(Numeric.cleanHexPrefix(tokenHash));
msg.append(Hex.toHexString(parInitCodeHash.getValue()));
String hash1 = Hash.sha3("0x" + msg.toString());
//对应这段代码 uint(keccak256(abi.encode(tokenA,tokenB,fee)))
BigInteger uintAddress = Numeric.toBigInt(hash1);
DynamicArray<Uint256> array = new DynamicArray<>(Uint256.class, new Uint256(uintAddress));
BigInteger uint256 = array.getValue().get(0).getValue();
String s3 = Numeric.toHexString(uint256.toByteArray());
String pairAddress = s3.substring(s3.length() - 40);
return "0x" + pairAddress;
}
//排序
public static List<String> sortTokens(String tokenA, String tokenB) {
Address address1 = new Address(tokenA);
Address address2 = new Address(tokenB);
BigInteger value1 = address1.toUint().getValue();
BigInteger value2 = address2.toUint().getValue();
List<String> result = new ArrayList<>();
if (value1.compareTo(value2) < 0) {
result.add(tokenA);
result.add(tokenB);
} else {
result.add(tokenB);
result.add(tokenA);
}
return result;
}
}
console
交易池地址:0x840deeef2f115cf50da625f7368c24af6fe74410
solidity代码
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
contract CalculatPoolAddress {
bytes32 internal constant POOL_INIT_CODE_HASH =
0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
// 0x1F98431c8aD98523631AE4a59f267346ea31F984,0xBe9895146f7AF43049ca1c1AE358B0541Ea49704,0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,500
function computeAddress(
address factory,
address token0,
address token1,
uint24 fee
) public pure returns (address pool) {
pool = address(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encode(token0, token1, fee)),
POOL_INIT_CODE_HASH
)
)
)
);
}
//abi.encode(token0, token1, fee)
function getEncodePacked() public pure returns (bytes memory) {
return
abi.encode(
0xBe9895146f7AF43049ca1c1AE358B0541Ea49704,
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
500
);
}
//keccak256(abi.encode(token0, token1, fee))
function getKeccak256EncodePacked() public pure returns (bytes32) {
return
keccak256(
abi.encode(
0xBe9895146f7AF43049ca1c1AE358B0541Ea49704,
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
500
)
);
}
//abi.encodePacked(hex"ff",factory,keccak256(abi.encode(token0, token1, fee)),POOL_INIT_CODE_HASH)
function getEncodePacked2() public pure returns (bytes memory) {
return
abi.encodePacked(
hex"ff",
0x1F98431c8aD98523631AE4a59f267346ea31F984,
keccak256(
abi.encode(
0xBe9895146f7AF43049ca1c1AE358B0541Ea49704,
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
500
)
),
POOL_INIT_CODE_HASH
);
}
//keccak256(abi.encodePacked(hex"ff",factory,keccak256(abi.encode(token0, token1, fee)),POOL_INIT_CODE_HASH))
function getKeccak256EncodePacked2() public pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
hex"ff",
0x1F98431c8aD98523631AE4a59f267346ea31F984,
keccak256(
abi.encode(
0xBe9895146f7AF43049ca1c1AE358B0541Ea49704,
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
500
)
),
POOL_INIT_CODE_HASH
)
);
}
}