I'm using Python Web3 and Uniswap to create a bot prototyp. I am currently trying to calculate the estimated pair price and I think I have done everything right. I have followed the following tutorial: https://dailydefi.org/articles/price-impact-and-how-to-calculate/

I actually calculate the output amount in the same way as in the tutorial. First I calculate the constant product by multiplying the two pool reserves. Then I divide the constant product by the reserve of token a + the deposited amount to calculate the new reserve of token b. Then I subtract this value from the old pool reserve for token b to get the output amount.

Here is the code of the estimated pair price:

    amount = 1
    reserves = pair_contract.functions.getReserves().call()

    token0_reserve = w3.fromWei(reserves[0], 'ether')
    token1_reserve = w3.fromWei(reserves[1], 'ether')

    constant_product = token0_reserve * token1_reserve
    new_token1_reserve = constant_product / (token0_reserve + amount)
    token1_out = token1_reserve - new_token1_reserve

I would expect that the "real" output from the uniswap router is nearly equal to that value but that wasnt so.

That is the Code for getting the real pair output:

        token0_amount = self.w3.toWei(1, 'ether')
        amount_out = self.uniswap_router_contract.functions.getAmountsOut(token0_amount, [self.w3.toChecksumAddress(token0_address), self.w3.toChecksumAddress(token1_address)]).call()
        amount_out = self.w3.fromWei(amount_out[1], 'ether')

And here is some log from the estimated pair price vs the real output price: Estimated pair price vs real output

Why do the prices for example WETH/SHIBASWAP differ so much between 0.00004 (estimated) and 27964.26725 (real out)?

Does my code have a bug or do I have a gap in understanding? I ask for help! Surely someone has had similar comprehension problems as I have... hopefully otherwise I feel stupid.


I finally fixed it!

And yes it was indeed a gap in my Uniswap knowledge.

I thought that the pool reserves are always stored in ether, but they are stored in the token amount with the appropriate decimal places.

So that others don't waste as much time as I did, here is the correct code:

    #Calculate Reserves of token a & b
    reserves = pair_contract.functions.getReserves().call()
    token0_reserve = float(reserves[token0_index])
    token0_reserve = token0_reserve / (10 ** token0_token_decimals)
    token1_reserve = float(reserves[token1_index])
    token1_reserve = token1_reserve / (10 ** token1_token_decimals)
    #Calculate constant product
    constant_product = token0_reserve * token1_reserve
    #Calculate new Token B Reserve
    new_token1_reserve = constant_product / (token0_reserve + amount)
    #Calculate Token B Output Amount
    token1_out = token1_reserve - new_token1_reserve

And this is how to get the correct output from uniswap:

        input_token_amount = input_token_amount * (10 ** input_token.token_decimals) 
        amounts_out = self.uniswap_router_contract.functions.getAmountsOut(input_token_amount, [self.w3.toChecksumAddress(input_token.token_address), self.w3.toChecksumAddress(output_token.token_address)]).call()
        amount_out = amounts_out[1] / (10 ** output_token.token_decimals) 

Hope that helps anybody, happy Coding!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.