Web3.py – How to Get a Uniswap Pool Address Using Web3.py

web3.py

I'm trying to get the address of a uniswap pool on chain, without using any graph or api. The uniswap v3 pool abi seems to have a getPool method that does exactly this.
I'm using that method but for some reason i get that a specific pool doesn't exist while it exists.

Here is an example

from web3 import Web3

abi = [{'inputs': [], 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'anonymous': False, 'inputs': [{'indexed': True, 'internalType': 'uint24', 'name': 'fee', 'type': 'uint24'}, {'indexed': True, 'internalType': 'int24', 'name': 'tickSpacing', 'type': 'int24'}], 'name': 'FeeAmountEnabled', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'internalType': 'address', 'name': 'oldOwner', 'type': 'address'}, {'indexed': True, 'internalType': 'address', 'name': 'newOwner', 'type': 'address'}], 'name': 'OwnerChanged', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'internalType': 'address', 'name': 'token0', 'type': 'address'}, {'indexed': True, 'internalType': 'address', 'name': 'token1', 'type': 'address'}, {'indexed': True, 'internalType': 'uint24', 'name': 'fee', 'type': 'uint24'}, {'indexed': False, 'internalType': 'int24', 'name': 'tickSpacing', 'type': 'int24'}, {'indexed': False, 'internalType': 'address', 'name': 'pool', 'type': 'address'}], 'name': 'PoolCreated', 'type': 'event'}, {'inputs': [{'internalType': 'address', 'name': 'tokenA', 'type': 'address'}, {'internalType': 'address', 'name': 'tokenB', 'type': 'address'}, {'internalType': 'uint24', 'name': 'fee', 'type': 'uint24'}], 'name': 'createPool', 'outputs': [{'internalType': 'address', 'name': 'pool', 'type': 'address'}], 'stateMutability': 'nonpayable', 'type': 'function'}, {'inputs': [{'internalType': 'uint24', 'name': 'fee', 'type': 'uint24'}, {'internalType': 'int24', 'name': 'tickSpacing', 'type': 'int24'}], 'name': 'enableFeeAmount', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}, {'inputs': [{'internalType': 'uint24', 'name': '', 'type': 'uint24'}], 'name': 'feeAmountTickSpacing', 'outputs': [{'internalType': 'int24', 'name': '', 'type': 'int24'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'address', 'name': '', 'type': 'address'}, {'internalType': 'address', 'name': '', 'type': 'address'}, {'internalType': 'uint24', 'name': '', 'type': 'uint24'}], 'name': 'getPool', 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [], 'name': 'owner', 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [], 'name': 'parameters', 'outputs': [{'internalType': 'address', 'name': 'factory', 'type': 'address'}, {'internalType': 'address', 'name': 'token0', 'type': 'address'}, {'internalType': 'address', 'name': 'token1', 'type': 'address'}, {'internalType': 'uint24', 'name': 'fee', 'type': 'uint24'}, {'internalType': 'int24', 'name': 'tickSpacing', 'type': 'int24'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'address', 'name': '_owner', 'type': 'address'}], 'name': 'setOwner', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}]

uni_v3_pool = '0x1F98431c8aD98523631AE4a59f267346ea31F984'

Infura_HTTP = '<MY-PROVIDER>'
w3 = Web3(Web3.HTTPProvider(Infura_HTTP))

univ3 = w3.eth.contract(uni_v3_pool, abi=abi)

eth = "0x0000000000000000000000000000000000000000"
cvx = '0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B'

print(univ3.functions.getPool(cvx, eth, 3000).call())

This code returns 0x0000000000000000000000000000000000000000, which means that the CVX-ETH pool doesn't exist, but according to Etherscan the pool exists: https://etherscan.io/address/0x2e4784446a0a06df3d1a040b03e1680ee266c35a. Why is that? Am i doing something wrong?

Best Answer

The method UniswapV3Factory.getPool(address tokenA, address tokenB, uint24 fee) returns the pool address of a given pair, given the pair token addresses and the pool's fee parameter.

The problem with your query above is that you've assigned eth the 0 address, but the correct way would be to assign it the mainnet WETH contract address which is 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2. As any ETH pair is actually realized with the WETH (Wrapped ETH) token.

As for the fee, if you want getPool(...) to return the pool address 0x2e4784446a0a06df3d1a040b03e1680ee266c35a, then the fee parameter should be 10000 as that's the pool fee as can be seen in the pool contract's storage. You could also try other different fee tiers to get different pools, while keeping the pool token pair tokens intact.

Related Topic