TAI
  • How does TAI work?
    • Overview
    • Supported Collaterals
    • Liquidations and Auctions
    • Tokenomics
    • Governance
      • Goverance Process
      • Governance Parameters
    • Rewards
    • Audits
  • TAI Protocol: In-depth
    • Contracts
      • System Contracts
        • Core Module
          • SAFE Engine
          • Liquidation Engine
          • Accounting Engine
        • Auction Module
          • Increasing Discount Collateral Auction House
          • Debt Auction House
          • Surplus Auction House
        • Oracle Module
          • Oracle Relayer
          • Medianizer
            • DSValue
            • Governance Led Median
            • Chainlink Median
          • FSM
            • Oracle Security Module
        • Token Module
          • Token Adapters
          • System Coin: TAI
          • Protocol Token: RATE
          • Protocol Token Authority
        • Money Market Module
          • Tax Collector
        • Sustainability Module
          • Stability Fee Treasury
          • FSM Wrapper
          • Increasing Treasury Reimbursement
          • Mandatory Fixed Treasury Reimbursement
        • Automation Module
          • Collateral Auction Throttler
          • Single Spot Debt Ceiling Setter
          • ESM Threshold Setter
        • Governance Module
          • DSPause
        • Shutdown Module
          • Global Settlement
          • ESM
      • Proxy Infrastructure
        • DSProxy
        • Proxy Registry
      • Helper Contracts
        • SAFE Manager
      • Contract Addresses
    • Data APIs
      • API Endpoints
Powered by GitBook
On this page
  • 1. Summary
  • 2. Contract Variables & Functions
  • 3. Walkthrough
  • 4. OSM Variations
  • 5. Gotchas (Potential Sources of User Error)
  • 6. Failure Modes (Bounds on Operating Conditions & External Risk Factors)
  • Authorization Attacks and Misconfigurations
  1. TAI Protocol: In-depth
  2. Contracts
  3. System Contracts
  4. Oracle Module
  5. FSM

Oracle Security Module

Basic price feed delay mechanism

1. Summary

The OSM (Oracle Security Module) ensures that new price values propagated from medianizers are not taken up by the system until a specified delay has passed. Values are updated using updateResult and read using read and getResultWithValidity. Each collateral type will have its own unique OSM. Collateral type is defined as a specific asset type (whereas ETH-A and ETH-B refer to the same asset and thus have the same OSM).

2. Contract Variables & Functions

Variables

  • authorizedAccounts[usr: address] - addresses allowed to call authed functions.

  • stopped - flag that disables price feed updates if non-zero

  • priceSource - address of medianizer that the OSM will read from

  • ONE_HOUR - 3600 seconds

  • updateDelay - time delay between updateResult calls; defaults to ONE_HOUR

  • lastUpdateTime - time of last update (rounded down to nearest multiple of updateDelay)

  • currentFeed - Feed struct that holds the current price value

  • nextFeed - Feed struct that holds the next price value

Modifiers

  • isAuthorized **** - checks whether an address is part of authorizedAddresses (and thus can call authed functions).

Functions

  • addAuthorization/removeAuthorization - add or remove authorized users (via modifications to the authorizedAccounts mapping)

  • stop()/start() - toggle whether the OSM price feed can be updated (by changing the value of stopped)

  • changePriceSource(address) - change data source for prices (by setting priceSource)

  • changeDelay(uint16) - change interval between price updates (by setting updateDelay)

  • restartValue() - similar to stop, except it also sets currentFeedand nextFeed to a Feed struct with zero values

  • getResultWithValidity() - returns the current feed value and a boolean indicating whether it is valid

  • getNextResultWithValidity() - returns the next feed value (i.e. the one that will become the current value upon the next updateResult() call), and a boolean indicating whether it is valid

  • read() - returns the current feed value; reverts if it was not set by some valid mechanism

  • updateResult() - updates the current feed value and reads the next one

Data Structures

  • Feed - struct used to store price feed data. Contains:

    • value - the feed value

    • isValid - whethet the feed value is valid

3. Walkthrough

In order for the OSM to work properly, an external actor must regularly call updateResult() to update the current price and read the next one. The contract stores the timestamp of the last updateResult() and will not allow another update until block.timestamp is at least lastUpdateTime + updateDelay. Values are read from the priceSource. In case of an oracle attack, governance can call stop() orrestartValue()

4. OSM Variations

SelfFundedOSM

ExternallyFundedOSM

5. Gotchas (Potential Sources of User Error)

N/A

6. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

updateCollateralPrice() is not called promptly, allowing malicious prices to be swiftly uptaken

For several reasons, updateCollateralPrice() is always callable as soon as block.timestamp / updateDelay increments, regardless of when the last updateCollateralPrice() call occurred (because lastUpdateTime is rounded down to the nearest multiple of updateDelay). This means the contract does not actually guarantee that a time interval of at least updateDelay seconds has passed since the last updateCollateralPrice() call before the next one; rather this is only (approximately) guaranteed if the last updateCollateralPrice() call occurred shortly after the previous increase of block.timestamp / updateDelay. Thus, a malicious price value can be acknowledged by the system in a time potentially much less than updateDelay.

This was a deliberate design decision. The arguments that favoured it, roughly speaking, are:

  • Providing a predictable time at which Prot holders should check for evidence of oracle attacks (in practice, updateDelay is 1 hour, so checks must be performed at the top of the hour)

  • Allowing all OSMs to be reliably updated at the same time in a single transaction

The fact that updateCollateralPrice is public, and thus callable by anyone, helps mitigate concerns, though it does not eliminate them. For example, network congestion could prevent anyone from successfully calling updateCollateralPrice() for a period of time. If a Prot holder observes that updateCollateralPrice has not been promptly called, the actions they can take include:

  1. Call updateCollateralPrice() themselves and decide if the next value is malicious or not

  2. Call stop() or restartValue() (the former if only nextFeed is malicious; the latter if the malicious value is already in currentFeed)

  3. Trigger emergency shutdown (if the integrity of the overall system has already been compromised or if it is believed the rogue oracle(s) cannot be fixed in a reasonable length of time)

In the future, the contract's logic may be tweaked to further mitigate this (e.g. by only allowing updateCollateralPrice() calls in a short time window each updateDelay period).

Authorization Attacks and Misconfigurations

Various damaging actions can be taken by authorized individuals or contracts, either maliciously or accidentally:

  • Revoking access of core contracts to the methods that read values, causing mayhem as prices fail to update

  • Completely revoking all access to the contract

  • Changing src to either a malicious contract or to something that lacks a getResultWithValidity() interface, causing transactions that updateCollateralPrice() the affected OSM to revert

  • Calling disruptive functions like stop and restartValue inappropriately

The only solution to these issues is diligence and care regarding the authorizedAccounts of the OSM.

PreviousFSMNextToken Module

Last updated 1 year ago

This contract pulls funds from the so it can reward addresses for callingupdateResult.

This contract calls an in order to reward addresses that call updateResult.

StabilityFeeTreasury
FSMWrapper