OnDemand Oracle

What is OnDemand Oracle

To build a genuinely permissionless margin trading market, we decided not to rely on oracles that pipe off-chain prices on-chain to support risk calculation. Instead, we use TWAP (Time-weighted average price) provided by Uniswap (or its forks) to build OnDemand Oracle that is updated based on trading interest to prevent price manipulation in the permissionless market and risk calculation with a real-time native on-chain price.

How It Protect for Uniswap V2 & Forks

Uniswap V2 provides a cumulative sum on a per-second basis. To calculate an accurate TWAP, it needs to check the sum at the beginning of a period and once at the end.

Extra Storage For Price

On top of the cumulative sum representing the latest TWAP for a pair on Uniswap V2, we record the latest price and cumulative sum using the following struct.

struct V2PriceOracle {    
    uint32 blockTimestampLast;  // BlockTime of last update
    uint price0;                // TWAP for token0
    uint price1;                // TWAP for token1
    uint price0CumulativeLast;  // Cumulative TWAP for token0
    uint price1CumulativeLast;  // Cumulative TWAP for token1

With the V2PriceOracle updated, we can calculate the current TWAP:

Using this equation allows us with three types of prices:

  • Last recorded TWAP

  • Latest TWAP derived from the recorded block

  • Latest spot price (derived from reserves of LP pools)

Price Validation

We calculate three different minimum collateral ratios from three reference prices to protect the protocol from price manipulation: last recorded TWAP, latest TWAP, and latest spot price. Its collateral ratio must be greater than all three ratios calculated for any new position. Correspondingly, for any position to be liquidated, its collateral ratio must be less than all three ratios calculated. Thereby, mitigating flash loan attacks as it can only manipulate the spot price within a single block, but not TWAP.

Price manipulation with large trades is still theoretically possible, but it has to push the price at least 50% (assuming 2X supported for the market) and stand up for at least one minute to be profitable. In a liquidity pool with decent liquidity depth and frequent trade activity, price manipulation with large trades will be risky and costly to do.

Oracle Update

Oracle allows updates only if the last update executed at least 60s ago and current TWAP deviates from the last recorded TWAP by more than 5%.

If the current TWAP deviates too much from the last recorded TWAP, new positions and liquidations may be rejected and a manual update is required. However, for closing healthy positions, no update is required. Successful trades also update the recorded price automatically.

Therefore, an active market with relatively smooth price movement would constantly update recorded TWAP prices and make most of the trades without updating the oracle.

The following figure gives an example of how we calculate minimum collateral ratios using all 3 prices.

How to Protect for Uniswap V3

Uniswap V3 offers significant improvements to the TWAP oracle, making it possible to calculate any recent TWAP within the past ~9 days from a single on-chain call.

This allows us to calculate TWAP from the two previous blocks. We can also enforce any new position or liquidation to meet the collateral ratio requirement calculated from these three prices: TWAP between T-2 and T-1 block, TWAP from T-1 and now, and spot price.

No oracle updates are needed for pair trading on Uniswap V3..

Last updated