Integration of the Chainlink RAI/USD Oracle

BT
Reflexer
Published in
5 min readDec 13, 2021

Background

The market price of RAI is used in the RAI system to determine a deviation (aka “error”) from the system’s redemption price. In turn, this error is used by the PI/D controller (Money God) to calculate a new redemption rate, increasing or decreasing the internal value of RAI and influencing market participants to correct the deviation.

See here for a refresher on how the PID controller influences the system.

This market price is read into the system from the RAI/USD oracle which has been recently updated. This post will introduce the new RAI Chainlink price feed used in the core protocol.

The Previous RAI/USD Oracle

The previous RAI/USD oracle derived a RAI/USD TWAP(Time-Weighted Average Price) by combining the RAI/ETH Uniswap V2 TWAP with a TWAP of the Chainlink ETH/USD feed used in the RAI system.

Below is the relevant portion of the system diagram with the previous oracle. The UniswapMedianRAIUSD contract received the ETH/USD price from the ChainlinkRelayer and RAI/ETH price information from the Uniswap V2 RAI/ETH pair.

Creating a RAI/USD TWAP from RAI/ETH and ETH/USD TWAPs led to some errors as outlined in this post and also didn’t cover market activity in other relevant pools or CEXes (e.g Coinbase, Uniswap v3, Curve). For these reasons, the oracle was upgraded from the Uniswap V2 Oracle to the current one, a TWAP of the Chainlink RAI/USD feed.

Current RAI/USD Oracle

Relevant changes to the system can be seen in the system diagram below. The ChainlinkTWAP contract now solely consumes RAI/USD prices coming from Chainlink and forms a TWAP. The ChainlinkRelayer still consumes the ETH/USD Chainlink feed for collateral pricing, but this feed is not used to construct the current RAI/USD price feed.

Chainlink RAI/USD Feed

Overview

The Chainlink RAI/USD feed is currently an aggregation of 16 off-chain oracles. The frequency of aggregated price updates, aka answers, are controlled by two trigger parameters.

Deviation Threshold: the percentage the off-chain aggregated price must move (up or down) before a new on-chain answer is set
Staleness Threshold: the longest time (in seconds) between two consecutive updates until a new oracle update is pushed on-chain

The current settings for the Chainlink RAI/USD feed are:

Deviation Threshold = 2%
Staleness: 24 hours

Therefore, if the median price of the oracle moves more than 2% or if there have been at least 24 hours since the last update, Chainlink will push a new price in their contract.

To learn more about Chainlink feeds and their architecture, you can read the Chainlink docs.

Chainlink RAI/USD in Action

Let’s observe the Chainlink RAI/USD feed over a recent time window. Below, you can see a chart with the Chainlink RAI/USD feed along with the RAI spot price and spot price moving averages.

Observation: all of the Chainlink updates are driven by staleness, not RAI/USD price action

In the chart above, the Chainlink feed (blue) only updates every 24 hours (the current staleness threshold for the feed).

The current deviation threshold of 2% is higher than typical RAI volatility so the Chainlink feed is not updating too often.

Deviation Thresholds

Assuming a market price equal to the current target price of $3.03, the following are the prices at which the possible Chainlink deviation thresholds would trigger oracle updates.

Here are these deviation thresholds plotted against the same time period.

From observing this window, the current deviation threshold of 2% appears to be too high as it outside of most RAI/USD price action. Except for a few spikes, the price action in this window will not trigger a Chainlink update. Switching the Chainlink deviation threshold to 1% or 0.5% would most likely create a more representative price feed.

Reflexer Chainlink RAI/USD TWAP

Overview

The Reflexer Chainlink TWAP contract creates a TWAP from periodic samples of the Chainlink RAI/USD feed. This TWAP represents the RAI/USD market price used internally by the PI/D controller to determine the deviation between market and target prices and calculate a new redemption rate.

Using a TWAP instead of the spot Chainlink RAI/USD price allows the system to be more resilient against market noise and possible manipulation of the RAI/USD market price. It also means that the controller will react to longer term deviations between market and redemption prices.

Chainlink TWAP Parameters

TWAP Calculation

The Chainlink TWAP is calculated starting from the last granularity Chainlink feed observation. Each observation is multiplied by the time passed since the previous update. The total time period window the TWAP represents can adjust from 1 day up to 4 days, but will always be composed of 3 time-weighted Chainlink feed samples.

Example:

Let: granularity=3 and consider the following series of Chainlink price samples:

When the Chainlink TWAP is updated, the most recent 3 prices and their previous time period weights in green will be used to calculate the current TWAP.

The TWAP calculation for this example:

Reflexer Chainlink TWAP in Action

Here is a plot of the same time window above, but with the Chainlink TWAP values included.

Here’s the same plot zoomed out to a longer time period.
Note: there is missing data on Nov. 16th and 17th.

Let’s compare the new TWAP represented above to the old TWAP plotted below, albeit during different time periods.

From these charts, we can see the new TWAP, derived from Chainlink RAI/USD, is less volatile and is arguably more representative of general RAI/USD market behavior, even with the current sub-optimal 2% deviation threshold of the Chainlink feed.

Next Steps

In a future post, we will observe the Chainlink RAI/USD TWAP with a reduced deviation threshold and how the threshold affects the RAI controller responsiveness.

References

Chainlink RAI/USD feed

Reflexer Chainlink TWAP contract

--

--