Structure
Contracts

Contracts

Overview

Our smart contracts work by making continuous observations of the current on-chain state of various decentralized exchanges (DEXs). Specifically, our contracts track prices and liquidity levels across various DEXs, then aggregates the data to produce secure and reliable data feeds.

We define three types of contracts to provide secure data feeds:

  1. Accumulators: At the lowest level, accumulators collect observations from various DEXs.
  2. Intermediate oracles: Intermediate oracles use data from accumulators to collect, produce, and store derived data such as time-weighted average price and liquidity at a single source.
  3. Aggregator oracles: Aggregators combine data from multiple sources and reduce them to singular data points.

At a high level, this flow chart explains how the three types of contracts interact: High level flow chart

Components

Accumulators

Accumulators are designed to track changing values such as prices and liquidities, allowing for time-weighted averages to be calculated from two unique accumulations. They also have a dual function of being spot oracles - that is, oracles that provide current values for whatever is being consulted. These spot oracles are more secure than reading straight from the DEX through the use of off-chain validation prior to observations being stored.

Accumulators all extend AbstractAccumulator, providing functionality to calculate relative changes and to store new observations when the relative change surpasses the defined update threshold.

Abstract accumulator flow chart

There are two distinct types of accumulators: price accumulators and liquidity accumulators.

Price accumulators

Price accumulators track prices across various DEXs with each different price accumulator tracking the prices at a specific DEX against a specific quote token. When the price at the DEX changes relative to the accumulator's stored (observed) price by more than the set update threshold, it's the responsibility of an updater bot to call the accumulator's update function to make a new observation.

Price accumulator flow chart

We noted earlier that consulting accumulators is more secure than directly consulting the DEX. This is because our updater bots provide a price to validate against before storing the observed price. This validation price is the price observed at the DEX as of a few blocks prior and is additionally validated off-chain against the price at Binance. The updater bot submits an update transaction only if the off-chain validation passes. See the updaters page for more information.

Price accumulator update flow chart

If the on-chain price validation passes, the price at the DEX is stored on-chain for later consultation. The DEX price is calculated as follows, depending on the specific DEX.

Price accumulator fetch price flow chart

Liquidity accumulators

Liquidity accumulators track liquidity levels across various DEXs with each different accumulator tracking the liquidity levels at a specific DEX in terms of token and quote token liquidity. When the liquidity at the DEX changes relative to the accumulator's stored (observed) liquidity by more than the set update threshold, it's the responsibility of an updater bot to call the accumulator's update function to make a new observation.

Liquidity accumulator flow chart

We noted earlier that consulting accumulators is more secure than directly consulting the DEX. This is because our updater bots provide liquidity levels to validate against before storing the observed liquidity. This validation liquidity is the liquidity observed at the DEX as of a few blocks prior. See the updaters page for more information.

Liquidity accumulator update flow chart

If the on-chain liquidity validation passes, the liquidity at the DEX is stored on-chain for later consultation. The DEX liquidity is calculated as follows, depending on the specific DEX.

Liquidity accumulator update threshold flow chart

Intermediate oracles

Intermediate oracles use data from accumulators to collect, produce, and store derived data such as time-weighted average price and liquidity at a single source.

The sole intermediate oracle contract in use is PeriodicAccumulationOracle. This contract takes a price accumulator, a liquidity accumulator, a quote token, and a period as arguments. Every period number of seconds, the update function is called by an updater bot. Upon update, as long as the underlying accumulators are up-to-date, cumulative price and liquidity is taken from the respective accumulators and stored. Using the last cumulative values and the new ones, a time-weighted average price and liquidity levels are calculated and stored for later consultations.

Aggregator oracles

Aggregators combine data from multiple sources and reduce them to singular data points.

The sole aggregator oracle contract in use is AggregatedOracle. This contract takes a set of underlying (intermediate) oracles, quote token information, a period, and minimum required liquidity values as arguments. Every period number of seconds, the update function is called by an updater bot. Upon update, all underlying oracles are updated and then consulted. As long as the required minimum number of valid consultations (currently just one) is met, the price and liquidity from the valid consultations is aggregated and a final price and liquidity levels are stored for later consultation.

An underlying oracle consultation is considered valid if:

  • The consultation's observational age is less than the AggregatedOracle's period, and
  • The price and quote token liquidity are not zero, and
  • The quote token liquidity is at least the minimum required, and
  • The token liquidity value (denominated in the quote token) is at least the minimum required, and
  • The ratio of the liquidity value distribution is within the range of 10:1 and 1:10

As long as the number of valid underlying oracle consultations meets the required number (currently just one), a harmonic mean price is calculated, weighted by quote token liquidity. This mean price as well as the summation of token liquidity and quote token liquidity are all stored for later consultation.

The harmonic mean is used as it produces more accurate averages when used with rates. The harmonic mean is weighted by quote token liquidity as prices are more accurate where liquidity is higher (less slippage).

A high level overview of the AggregatedOracle contract is as follows: Aggregated oracle scheme