freeearth
freeearth

Reputation: 101

Compute uniswap 3.0 pool (pair) address via python3

I stucked a little bit with a problem how to compute new uniswap`s version 3 pool (earlier versions it called pair) address based on 1 and 2

Upvotes: 2

Views: 2310

Answers (1)

freeearth
freeearth

Reputation: 101

In the new uniswap v3.0 there is also one additional parameter for computing pool address - fees amount in percents, defined like in sdk with uint24 type. From sdk`s computePoolAddress at the first times settled with computing pool address problem there was one confused me part of the source

[defaultAbiCoder.encode(['address', 'address', 'uint24'], [token0.address, token1.address, fee])

And somewhy I decided to compute it using encodePacked (i.e. encode_abi_packed for python3 from eth_abi.packed) function. But it produced wrong result. Look deeper in the uniswap v3.0 periphery pool conract - 3 clarified my mistake. It turns out in version 3.0 using encode (i.e. encode_abi for python3 from eth_abi) function. A little bit more explanations here

So, coupled all together.

Main function to compute pool address with the aids of python3.

from web3 import Web3
from eth_abi.packed import encode_abi_packed
from eth_abi import encode_abi

def compute_pairs_address_with_target_v3(factory = '0x1F98431c8aD98523631AE4a59f267346ea31F984', token_0 = None, token_1 = None, fee = 3000):
    POOL_INIT_CODE_HASH = '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'
    token_0 = Web3.toChecksumAddress(token_0)
    token_1 = Web3.toChecksumAddress(token_1)
    abiEncoded_1 = encode_abi(['address', 'address', 'uint24'], (token_0, token_1, fee )) if int(token_0,16)<int(token_1,16) else encode_abi(['address', 'address', 'uint24'], (token_1, token_0, fee ))
    salt = Web3.solidityKeccak(['bytes'], ['0x' +abiEncoded_1.hex()])
    abiEncoded_2 = encode_abi_packed([ 'address', 'bytes32'], ( factory, salt))
    resPair = Web3.solidityKeccak(['bytes','bytes'], ['0xff' + abiEncoded_2.hex(), POOL_INIT_CODE_HASH])[12:]
    return(resPair.hex())

Testing it, based on 4 and 5

factoryAddress = '0x1111111111111111111111111111111111111111'
token0 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
token1 = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
fee = 500 #https://docs.uniswap.org/sdk/reference/enums/FeeAmount#low
targetPoolAddress = '0x90B1b09A9715CaDbFD9331b3A7652B24BfBEfD32'
assert(targetPoolAddress.lower() == compute_pairs_address_with_target_v3(factory = factoryAddress, token_0 = token0, token_1 = token1, fee = fee).lower())

token0 = '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0'
token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
factoryAddress = '0x1F98431c8aD98523631AE4a59f267346ea31F984'
fee = 3000 #https://docs.uniswap.org/sdk/reference/enums/FeeAmount#medium
targetPoolAddress = '0x290a6a7460b308ee3f19023d2d00de604bcf5b42' #WETH /MATIC 0.3 % fee
assert(targetPoolAddress.lower() == compute_pairs_address_with_target_v3(factory = factoryAddress, token_0 = token0, token_1 = token1, fee = fee).lower())

Upvotes: 3

Related Questions