7.6 Uniswap v3 Pricing Oracles —> (Uniswap V3 whitepaper)
Last updated
Last updated
As in Uniswap v2, Uniswap v3 tracks a running accumulator of the price at the beginning of each block, multiplied by the numberof seconds since the last block.
A pool in Uniswap v2 stores only the most recent value of this price accumulator—that is, the value as of the last block in which a swap occurred. When computing average prices in Uniswap v2, it is the responsibility of the external caller to provide the previous value of the price accumulator. With many users, each will have to provide their own methodology for checkpointing previous values of the accumulator, or coordinate on a shared method to reduce costs. And there is no way to guarantee that every block in which the pool is touched will be reflected in the accumulator.
In Uniswap v3, the pool stores a list of previous values for the price accumulator (as well as the liquidity accumulator described in section. It does this by automatically checkpointing the accumulator value every time the pool is touched for the first time in a block, cycling through an array where the oldest checkpoint is eventually overwritten by a new one, similar to a circular buffer. While this array initially only has room for a single checkpoint, anyone can initialize additional storage slots to lengthen the array, extending to as many as 65,536 checkpoints. This imposes the one-time gas cost of initializing additional storage slots for this array on whoever wants this pair to checkpoint more slots.
The pool exposes the array of past observations to users, as well as a convenience function for finding the (interpolated) accumulator value at any historical timestamp within the checkpointed period
V2 oracles work by storing cumulative sums of Uniswap pair prices on a per-second basis. These price sums can be checked once at the beginning of a period and once at the end to calculate an accurate TWAP over that period.
Uniswap v3 offers significant improvements to the TWAP oracle, making it possible to calculate any recent TWAP within the past ~9 days in a single on-chain call. This is achieved by storing an array of cumulative sums instead of just one.
This array of historical price accumulators makes it far easier and cheaper to create more advanced oracles that include simple-moving averages (SMA), exponential moving averages (EMA), outlier filtering, and more.
Despite this major improvement, the gas cost to Uniswap traders for keeping oracles up to date has been reduced by ~50% relative to v2. The costs for calculating TWAPs in external smart contracts is significantly cheaper as well.
The SMA is a financial instrument representing the simple moving average calculated over a range of prices distributed over a defined time period.
The SMA provides a more reliable measurement than the EMA because the weights of each price are the same, making it difficult to manipulate the SMA by acting on the latest prices.
The EMA is a financial instrument representing the exponential average moved, and places a greater relevance on the most recent prices of the time interval considered.
This tool proves to be particularly useful in case of liquidation of tokens, since the weight of prices is not equal and the most recent values transpire better in the EMA.
An oracle that makes use of the EMA formula is easier to manipulate, since a hypothetical attacker could cause more important fluctuations in the EMA value than the recent volumes he moved for the attack.