In May of this year, Vitalik created a post on the Uniswap governance forum called, “UNI should become an oracle token.” He argues that there is a need for oracles to provide off-chain data, and that UNI is in a good position to provide an alternative to Chainlink for high-value, latency-tolerant use cases.
While it’s an interesting idea, as I reflected on that post recently, I was thinking about how Uniswap already is an oracle protocol. It already provides a price feed from the largest DEX on Ethereum. UNI already is an oracle token, the UNI DAO just hasn’t done much with that fact, as of yet at least.
Ever since v1, Uniswap has been an oracle protocol, albeit a very crude one at the time. Uniswap v1 was a series of ETH-ERC20 pools with a simple
x * y = k pricing mechanism. You could query for the values of the ETH and the respective ERC20 token in any pool, and viola, you have a spot price oracle.
v1 leaves a lot to be desired as an oracle protocol, however. First, everything was priced in ETH. In order to get a non-ETH quote, say the price of BAT in terms of USDC, you would need to chain prices together (in this case, BAT-ETH and ETH-USDC).
Second, the price was a simple point-in-time (and more specifically and tragically, point-in-a-block) spot price. This is vulnerable to manipulation, as an “unfortunately timed” liquidity withdrawal and large trade could swing the price dramatically. I wouldn’t recommend relying on that price for a sensitive task like determining if a borrow position is underwater.
v2 improved on the utility of Uniswap as an oracle. First, v2 allowed for any arbitrary ERC20-ERC20 pair. Second, each pool took a snapshot of the price at the beginning block before any trade or liquidity change had taken place, which made manipulation more difficult. Finally, the price value it stored (a running accumulator of the price multiplied by the seconds since the last block) allowed a user to calculate a time-weighted average price (TWAP) as opposed to a simple spot price.
Getting a TWAP from a v2 pool did not work out of the box, however--it required integrators to store past values of the running accumulator in a separate contract for calculation.
Uniswap v3 maintains the benefits offered in v2, but also addresses the aforementioned flaw by offering the ability to store a series of accumulator values (only 1 value is stored by default, but anyone willing to pay the gas cost can expand the number of tracked values to a maximum of 65,535 observations, or ~9 days of prices).
Uniswap v3 is already being used as an on-chain oracle in varied contexts.
A number of projects call Uniswap v3’s oracle function from their contracts, including:
These oracle calls are made across a wide variety of pairs. We can see in the figure below that while USDC-WETH is the most commonly called pair, it only comprises 17% of oracle calls. There is a long tail of assets for which the oracle functionality is used. A number of these are directly related to the protocols mentioned above (.e.g FRAX, KP3R). More, however, are simply assets for which Uniswap is likely one of the most significant sources of liquidity (e.g. ENS and of course ELON).
The oracle functionality is already being used, and that’s despite a relative dearth of material on the the performance of Uniswap oracles (though I refer you to an excellent thread on the cost of attacking a v3 oracle by Michael Bentley).
Where is the incentive to improve and maintain the oracle experience, however? Oracle usage doesn’t currently benefit traders, LPs, or maintainers of the protocol.
It’s worth considering a fee to use price oracles. While this would require some protocol changes, this could be implemented as a flat fee in ETH per call or a registration of a project’s contract on an array of approved oracle callers.
In exchange for these fees, the Uniswap DAO could become a “keeper of the oracles.” What would that mean in practice? The DAO could:
By “liquidity provider of last resort,” I mean the DAO could create an automated strategy or appoint an LP manager to provide certain amount of passive liquidity to pools that are important oracles and running low on liquidity. This could dissuade attacks as well as respond to attacks spanning multiple blocks that involve withdrawing liquidity or affecting the liquidity balance of a pool.
This discussion feels incomplete without acknowledging some of the limitations of the using Uniswap oracles as they exist today.
While using a simple spot price (as opposed to a TWAP) from an AMM is inadvisable, a TWAP reduces the freshness of your data (it adapts more slowly to changing market conditions by definition). In choosing the length of time over which to measure the TWAP, you face a dilemma:
Take a lending protocol for example. If the price of collateral hits a sudden downtrend, and the TWAP doesn’t reflect that a position is under-collateralized until 30 minutes after the start of the downtrend, the spot price by then may be even lower, which could cause the protocol to take a loss on the now possibly underwater position.
That being said, the attractive part of Uniswap oracles is they work relatively autonomously. Even without the extra assurances a DAO could provide, they would continue to work well just given the incentives of market participants.
Coming full circle back to Vitalik’s post, it could be interesting to explore how the DAO could use current pool TWAP model as one ingredient in an oracle solution that adds in fresher, off-chain sources of price data. Until then, I say a bird in the hand is worth
getTWAP(birdsInBush, birdsInHand, ‘30 minutes’) in the bush.
Image of the oracle at Delphi is ‘The Oracle’ by Camillo Miola (1880), source: Getty.
Dune analytics queries: