1

I am wondering if there is a function in smart contract pools to get historical data (just last 100 bars for example). thanks guys!

1 Answer 1

1

Yes, you can do this. This is not as much specifically a function in a smart contract but more like querying any contract function against a specific block. You need an archive node (instead of a full node) for that as an archive node contains all network states (identified by blocks) in the past that you can do a query against.

Let's use a Uniswap V3 LP for USDC-WETH as an example: 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640.

The function that you call to get the USDC-WETH exchange rate is slot0() (remember, the returned data is hex and square root).

Let's use eth_call to do a simple curl call to slot0() to get the exchange rate from the USDC-WETH pool.

Template

curl -X POST ARCHIVE_NODE_ENDPOINT \
-H "Content-Type: application/json" \
--data '{
  "jsonrpc":"2.0",
  "method":"eth_call",
  "params":[{
    "to": "CONTRACT_ADDRESS",
    "data":"FUNCTION_SIGNATURE"
  }, "BLOCK_NUMBER"],
  "id":1
}'

where:

  • ARCHIVE_NODE_ENDPOINT — you need an archive node.
  • CONTRACT_ADDRESS — An LP contract address. 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 in our case.
  • FUNCTION_SIGNATURE — convert slot0 to the function signature. For example, use an online tool, paste slot0 in Function name and parameters type and get 0x3850c7bd.
  • BLOCK_NUMBER — block number in hex or just latest.

Curl example

Here's the exchange rate of USDC-WETH at block 12489829.

curl -X POST ARCHIVE_NODE_ENDPOINT \
-H "Content-Type: application/json" \
--data '{
  "jsonrpc":"2.0",
  "method":"eth_call",
  "params":[{
    "to": "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640",
    "data":"0x3850c7bd"
  }, "0xBE9465"],
  "id":1
}'

As a side note, you need an archive node to go beyond the immediate 128 blocks in the past to get the data. If you are on the Ethereum mainnet (and on Geth, Erigon nodes) and query for state within the 128 blocks, you can get by with a full node. A full node prunes states past the 128 blocks by default, although this also depends on the node config.

Python example with exchange rate conversion

If you want to get actual exchange rate printed, here's Python code that gets the result with eth_call (same as the curl example) and then converts it following the Uniswap V3 primer.

import json
from web3 import Web3

# Load the UniswapV3Pool ABI from local file. You can get the ABI from https://etherscan.io/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640#code
with open('UniswapV3Pool_abi.json', 'r') as file:
    contract_abi = json.load(file)

# Have an Ethereum mainnet archive node here so we can fetch from any block in the past, not just the immediate past 128 blocks
w3 = Web3(Web3.HTTPProvider("ARCHIVE_NODE_ENDPOINT"))

# UniswapV3Pool for USDC-WETH
contract_address = "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# Make the eth_call to slot0 at block 12489829 (put any block)
result = contract.functions.slot0().call(block_identifier=12489829)

# Parse the result from the returned value following the struct https://etherscan.io/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640#code#F1#L58 // basically just getting the first value
sqrtPriceX96 = result[0]

# Calculate the price following https://blog.uniswap.org/uniswap-v3-math-primer
price = (sqrtPriceX96 / (2**96))**2

# Adjust for token decimals because USDC is 6 decimals and WETH is 18 decimals
adjPrice = price / 1e12

# Convert the price per WETH token to a more readable format
exchange_rate = 1 / adjPrice

# Print the exchange rate with 2f as a two-decimal floating number just for human readability
print(f'The exchange rate is {exchange_rate:.2f} USDC per WETH.')
7
  • thank you so much for the help, I managed to pull the data for the example above, the result is : 0x0000000000000000000000000000000000005699958e9f83ba1dea1c769656110000000000000000000000000000000000000000000000000000000000030dcb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 But I am not able to convert to readable format Oct 23 at 21:06
  • You said the returned data is hex and square root, I tried to covert the data to readable format but no luck, I also used alchemy api for the archive node Oct 23 at 21:08
  • I finally managed to convert the hex value to float and after square root the result is : 6.506616883820552382941721992E+247 it's false obviously the value of eth should be around 1650 I think Oct 23 at 21:50
  • I added Python code to do the conversion too.
    – Ake
    Oct 23 at 23:40
  • I apologize for inconveniencing, the result of the code is this : "Exchange Rate USDC-WETH: 2.6074282406289621803866375815174726108106586707927E+962" still not able to understand how to interpret it, thank you for the valuable help Oct 24 at 0:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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