计算uniswap v3交易池子地址

计算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
                )
            );
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值