Euler Price Oracles is a library of modular oracle adapters and components that implement IPriceOracle
, a quote-based interface compatible with ERC-7726.
-
To read more about the design and motivation behind
IPriceOracle
and the oracles in this repo, check out the whitepaper and ERC-7726. -
To understand how Price Oracles fit into the Euler Vault Kit, check out the price oracles section of the EVK whitepaper.
-
To use or develop with Euler Price Oracles, check out the Usage section.
-
To find out ways to contribute to Euler Price Oracles, check out the Contributing section.
-
To observe 200+ live deployments of these oracle adapters check out the dedicated Oracle Dashboard.
Euler Price Oracles has been audited by Spearbit, OpenZeppelin, ChainSecurity, Omniscia, yAudit, and Cantina.
All contracts in this library implement the IPriceOracle
interface.
/// @return outAmount The amount of `quote` that is equivalent to `inAmount` of `base`.
function getQuote(
uint256 inAmount,
address base,
address quote
) external view returns (uint256 outAmount);
/// @return bidOutAmount The amount of `quote` you would get for selling `inAmount` of `base`.
/// @return askOutAmount The amount of `quote` you would spend for buying `inAmount` of `base`.
function getQuotes(
uint256 inAmount,
address base,
address quote
) external view returns (uint256 bidOutAmount, uint256 askOutAmount);
This interface shapes oracle interactions in an important way: it forces the consumer to think in amounts rather than prices.
A subset of this interface (getQuote
) has been standardized in ERC-7726.
Euler Price Oracles are unique in that they expose a flexible quoting interface instead of reporting a static price.
Note
Imagine a Chainlink price feed which reports the value 1 EUL/ETH
, the unit price of EUL
. Now consider an IPriceOracle
adapter for the feed. It will fetch the unit price, multiply it by inAmount
, and return the quantity inAmount EUL/ETH
. We call this a quote as it functionally resembles a swap on a decentralized exchange.
The quoting interface offers several benefits to consumers:
- More intuitive queries: Oracles are commonly used in DeFi to determine the value of assets.
getQuote
does exactly that. - More expressive interface: The unit price is a special case of a quote where
inAmount
is one whole unit ofbase
. - Safe and flexible integrations: Under
IPriceOracle
adapters are internally responsible for converting decimals. This allows consumers to decouple themselves from a particular provider as they can remain agnostic to its implementation details.
Euler Price Oracles additionally expose getQuotes
which returns two prices: the selling price (bid) and the buying price (ask).
Bid/ask prices are inherently safer to use in lending markets as they can accurately reflect instantaneous price spreads. While few oracles support bid/ask prices currently, we anticipate their wider adoption in DeFi as on-chain liquidity matures.
Importantly getQuotes
allows for custom pricing strategies to be built under the IPriceOracle
interface:
- Querying two oracles and returning the lower and higher prices.
- Reporting two prices from a single source e.g. a TWAP and a median.
- Applying a synthetic spread or a volatility-dependent confidence interval around a mid-price.
An adapter is a minimal, fully immutable contract that queries an external price feed. It is the atomic building block of the Euler Price Oracles library.
The IPriceOracle
interface is permissive in that it does not prescribe a particular way to implement it. However the adapters in this library adhere to a strict set of rules that we believe are necessary to enable safe, open, and self-governed markets to flourish.
Adapters are fully immutable without governance or upgradeability.
An adapter connects to one pricing system and queries a single price feed in that system.
An adapter works in both directions. If it supports quoting X/Y
it must also support Y/X
.
An adapter's parameters and acceptance logic are easily observed on-chain.
Adapter | Type | Method | Supported Pairs | Parameters |
---|---|---|---|---|
ChainlinkOracle | External | Push | Provider feeds | feed, max staleness |
ChronicleOracle | External | Push | Provider feeds | feed, max staleness |
PythOracle | External | Pull | Provider feeds | feed, max staleness, max confidence interval |
RedstoneCoreOracle | External | Pull | Provider feeds | feed, max staleness, cache ttl |
LidoOracle | Onchain | Rate | wstETH/stETH | - |
LidoFundamentalOracle | Onchain | Rate | wstETH/ETH | - |
UniswapV3Oracle | Onchain | TWAP | UniV3 pools | fee, twap window |
PendleOracle | Onchain | TWAP | Pendle markets | pendle market, twap window |
RateProviderOracle | Onchain | Rate | Balancer rate providers | rate provider |
FixedRateOracle | Onchain | Rate | Any | rate |
To install Price Oracles in a Foundry project:
forge install euler-xyz/euler-price-oracle
Clone the repo:
git clone https://github.com/euler-xyz/euler-price-oracle.git && cd euler-price-oracle
Install forge dependencies:
forge install
[Optional] Install Node.js dependencies:
npm install
Compile the contracts:
forge build
The repo contains 4 types of tests: unit, property, bounds, fork, identified by their filename suffix.
To run fork tests set the ETHEREUM_RPC_URL
variable in your environment:
# File: .env
ETHEREUM_RPC_URL=...
Alternatively, to exclude fork tests:
forge test --no-match-contract Fork
Important
Tests in RedstoneCoreOracle.fork.t.sol
use the ffi
cheatcode to invoke a script that retrieves Redstone update data. FFI mode is not enabled by default for safety reasons. To run the Redstone Fork tests set ffi = true
in foundry.toml
.
Euler Price Oracles is a free and open-source public good. We encourage you to engage and contribute.
Feel free to open a GitHub issue discussing your ideas.
Tip
Submit testing- and documentation-related PRs to development
and changes under src/
to experiments
.
Here are a few ideas how you can improve Euler Price Oracles:
- Write an adapter for a new oracle provider or an AMM such as Curve V2.
getQuotes
returns bid/ask prices, however we are not aware of any oracle providers that currently support them. Write anIPriceOracle
wrapper that applies a price spread around a mid-point price. The spread could be dynamic based on proxy metrics such as liquidity, volume, (implied) volatility, correlation. We are highly interested in research towards this direction.- ZK Coprocessors like Axiom and Lagrange allow you to verifiably compute over historical blockchain state in ZK circuits. This unlocks a new design space for trust-minimized manipulation-resistant oracles. Write a proof-of-concept oracle using a ZK Coprocessor. Some ideas: an implied volatility oracle based on Uniswap V3, a median filtering oracle over an AMM.
- Write an
IPriceOracle
wrapper that implements a trustless circuit-breaker mechanism that detects failure conditions. Upon detection it could switch to another oracle or redeploy the adapter with different parameters. - Write an alternative router to
EulerRouter
that supports more flexible configuration. - Research whether a DEX aggregator API can be used as a pull-based price oracle and write a proof-of-concept adapter.
- Some oracle providers are compatible with Chainlink's
AggregatorV3Interface
either directly or through a facade contract. Are they safe to use throughChainlinkOracle
in this library? - Write a sanity checking script that verifies an adapter is correctly configured by comparing the quote against a price API.
- Write a simulation script that generates a line plot comparing a given adapter's prices against a price API historically.
- Expand the fork test suite to include more pairs and to historically backtest the adapter.
- Write fuzz and invariant tests using echidna, medusa, or foundry.
- Write formal verification tests using Certora, halmos, or kontrol.
EulerRouter
can price ERC4626 shares to assets by callingconvertToAssets
. Which of the currently live vaults have a manipulation-resistant pricing function?- With pull-based oracles users control the price update flow. What is an appropriate value for
maxStaleness
on Ethereum considering network delays and possible censorship? Are there waysmaxStaleness
can be safely reduced? - Are these oracles readily usable on the various L2s or are there additional considerations that must be had?
- Write an smart contract integration guide for Euler Price Oracles.
- Write a frontend integration guide for fetching the price of pull-based oracles.
- Write or compile risk research for a provider, detailing how it works, its failure modes and trust assumptions.
This software is experimental and is provided "as is" and "as available".
No warranties are provided and no liability will be accepted for any loss incurred through the use of this codebase.
Always include thorough tests when using Euler Price Oracles to ensure it interacts correctly with your code.
(c) 2024 Euler Labs Ltd.
The Euler Price Oracles code is licensed under the GPL-2.0-or-later license.