Uniswap as an Oracle Price Feed
Introduction
One of the underappreciated features of Unsiwap is its utility as a Price Oracle. In this recipe, we will use the Sync
log event to calculate a Price Feed. This recipe is broken down into three steps:
- Find the topic hash for a
Sync
event. - Use the Covalent API to fetch the event logs.
- Calculate the Price feed using data from step 1 and 2 above.
Prerequisites
Endpoints Summary
The key Covalent API endpoints covered here are:
v1/{chainId}/events/topics/{topic}/
- Return a paginated list of decoded log events with one or more topic hashes separated by a comma.
Extracting an exchange contract Sync
event
For illustrative purposes, we will pick the USDC-ETH
uniswap pool at the address 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc
.
1) Find the topic hash for Sync
events
On Etherscan, we see the events emitted from this contract:
We see that the topic hash for the Sync
event is 0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1
.
Another way to calculate the topic hash is to use the Covalent Topic Hash Calculator.
2) Use the Covalent API v1/{chainId}/events/topics/{topic}/
endpoint to fetch the event logs
The Covalent API GET log events by topic hash endpoint lets you fetch fully decoded events logs. You can call it with the following parameters:
Parameter | Value |
---|---|
chainId |
1 |
topic |
0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1 |
starting-block |
11995619 |
ending-block |
latest |
sender-address |
0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc |
Also note that the sender-address
is our USDC-ETH
pool contract address.
Our response from the Covalent API looks something like this (only 1 record shown):
{
"data": {
"updated_at": "2021-03-08T06:36:13.987447062Z",
"items": [
{
"block_signed_at": "2021-03-08T04:12:30Z",
"block_height": 11995619,
"tx_offset": 130,
"log_offset": 213,
"tx_hash": "0x26337bdeec5badee6f52c571a4785ee1fac956df2e2c29b313ffae0477045f53",
"_raw_log_topics_bytes": null,
"raw_log_topics": [
"0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1"
],
"sender_address": "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
"sender_address_label": null,
"raw_log_data": "0x000000000000000000000000000000000000000000000000000074e25ab853df000000000000000000000000000000000000000000000fd828ec5f992412fd40",
"decoded": {
"name": "Sync",
"signature": "Sync(uint112 reserve0, uint112 reserve1)",
"params": [
{
"name": "reserve0",
"type": "uint112",
"indexed": false,
"decoded": true,
"value": "128515533460447"
},
{
"name": "reserve1",
"type": "uint112",
"indexed": false,
"decoded": true,
"value": "74822942799933302046016"
}
]
}
},
...
]
}
}
The values under decoded.params
are the values of the two liquidity reserves of the USDT
and ETH
tokens in the pool.
3) Calculate the price
Before you can calculate the price from the Sync
event - you first need to understand how to format these reserves. The reserves are recorded using the contract decimals for the two tokens. In this case:
Token | Name | Decimals | Recorded value | Scaled value |
---|---|---|---|---|
USDC | USD Coin | 6 | 128515533460447 | 128,515,533.460447 |
ETH | Ether | 18 | 74822942799933302046016 | 74,822.942799933302046 |
Therefore, the price of ETH
in the units of USDC
is
Next steps
Congratulations :tada: :sparkles: You have made a delicacy!
You can use this method to calculate token prices for any pool contract across any Uniswap-like AMM. For example, the same method works on PancakeSwap (Binance Smart Chain), QuickSwap (Matic), RamenSwap (Binance Smart Chain) and so on.
Just be aware that different tokens have different contract decimals and will need to be scaled accordingly.