Abstract Oracle

High-Level Overview

The AbstractOracle contract is inherited by the ClassicalOracle. It is not meant to be deployed on its own and is designed to safely be inherited by upgradable contracts, and upgradable contracts only.

Contract Summary

The shared logic contained in AbstractOracle includes:

  • Converting the price of the oracle of arbitrary decimals into wad (18 decimals)

  • Computing a quote (USD value) for a given token and amount of tokens

  • Making sure stablecoins haven’t depegged

  • Allowing the admin to set the maximum allowed price variation for stablecoins

The inheriting contracts are responsible for initializing the tokenToOracleInfo mapping as well as implementing _latestRoundData to handle the specific interaction for the corresponding oracle.

Inherited Contracts

  • IOracle: Common interface used by other contracts and external service (e.g. the dApp) to interact with UsualOracle and ClassicalOracle. Ensures function signatures are the ones expected by these external actors.

  • Initializable: Allows to handle contract setup and upgrades.

Functionality Breakdown

The main functionality of this contract is to get the price a given token by its address with getPrice. The AbstractOracle contract calls the virtual function _latestRoundData. It then converts the returned amount to 18 decimals. Finally, it runs the anti-depeg check for stablecoins.

The getQuote function calls getPrice internally, and then applies a cross-product to the amount given as parameter, yielding the final quote.

Functions Description

Public/External Functions

  • getMaxDepegThreshold(): Returns the current maximum allowed price variation for stablecoins in basis points (e.g. with a value of 500, getPrice and getQuote will revert if the price of a stablecoin is outside the range $0.95-$1.05). View function.

  • setMaxDepegThreshold(uint256 maxAuthorizedDepegPrice): Updates the maximum allowed price variation and emits a SetMaxDepegThreshold event. Nonpayable function. Reserved for admin use only.

  • getPrice(address token): Returns the price of the given token scaled to 18 decimals (e.g. a return value of 3e18 means the token price is $3). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.

  • getQuote(address token): Returns the USD value equivalent to the given amount of the given token (e.g. if the token price is $3, calling with 1e6 will return 3e6, no matter the number of decimals of the token). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.

Remediation Strategies

  • Off-chain data sources: We do not rely on on-chain oracles, such as Uniswap or Curve. These protocols could more easily be vulnerable to sandwich and/or flashloan attacks, enabling price manipulation.

  • Dual-oracle cross-verification: Not live yet, will require a future upgrade. Drawing inspiration from Liquity’s PriceFeed, we could add a secondary oracle and compare prices between the two. This would reduce the impact of one of the two oracles getting hacked or freezing. We had implemented such a system, but didn’t find any other reliable price feed for USDC, USDT, nor USYC.

Last updated