euler-xyz / euler-price-oracle

Euler Price Oracles, a library of immutable oracle adapters and components
https://docs.euler.finance/euler-price-oracle/
GNU General Public License v2.0
55 stars 8 forks source link
defi oracles price-oracle solidity

Euler Price Oracles

Euler Price Oracles is a library of modular oracle adapters and components that implement IPriceOracle, a quote-based interface compatible with ERC-7726.

Euler Price Oracles has been audited by Spearbit, OpenZeppelin, ChainSecurity, Omniscia, yAudit, and Cantina.

IPriceOracle

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.

Quotes

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:

Bid/Ask Pricing

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:

Oracle Adapters

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.

Design Principles

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.

Immutable

Adapters are fully immutable without governance or upgradeability.

Minimally Responsible

An adapter connects to one pricing system and queries a single price feed in that system.

Bidirectional

An adapter works in both directions. If it supports quoting X/Y it must also support Y/X.

Observable

An adapter's parameters and acceptance logic are easily observed on-chain.

Summary of Adapters

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

Usage

Install

To install Price Oracles in a Foundry project:

forge install euler-xyz/euler-price-oracle

Development

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

Testing

The repo contains 4 types of tests: unit, property, bounds, fork, identified by their filename suffix.

Fork Tests

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.

Contributing

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:

Research and Development

Security

Technical Documentation

Safety

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.

License

(c) 2024 Euler Labs Ltd.

The Euler Price Oracles code is licensed under the GPL-2.0-or-later license.