This is a draft proposal for a change that aims to improve the functionality of the stability mechanism. The change will update the SortedOracles contract and will introduce two new contracts to the mento protocol.
Simple Summary
- Design of an oracle report filter with modular filter conditions.
- Design of an oracle report price deviation filter condition.
Abstract
The Celo oracle client is currently responsible for running checks against new price reports before submitting them to the SortedOracles
contract. One of these checks determines if prices from data sources have a deviation greater than a specified threshold. If a report fails any of the checks, the oracle will ignore the report and will not send an update to the contract. This proposal is to move this functionality on-chain to allow new checks to be added easily in the future.
A new contract, the ReportFilter
, will be created and injected into the SortedOracles
contract. The new contract will act as a simple interface to allow the SortedOracles
to filter incoming reports without knowing the filter conditions, their dependencies or how they are checked. Filter conditions are created as separate modules to allow new ones to be added or removed independently in future updates.
Motivation
The Mento protocol relies on price reports from centralized oracle clients run by cLabs. Whilst cLabs is a trusted entity, as long as the protocol depends on the centralized oracle setup, it will remain a single point of failure for Mento. This change aims to move one of the current responsibilities, in addition to providing price reports, held by the oracle clients on-chain.
In addition to providing price reports, the oracle clients also perform additional checks before sending reports to the SortedOracles
contract:
- Before submitting a report, the oracle client pulls prices from all configured exchange data sources. The first of multiple checks verify that the prices received do not deviate more than a configurable value, the
maxPercentageDeviation
. If the deviation is too large, the oracle will not submit an update. - The next check determines if the current report price change relative to the last report price is greater than a calculated threshold. If the difference exceeds the threshold, the oracle circuit breaker will be opened, stopping the oracle client from reporting prices indefinitely.
- The last check determines if the current report price change is significant enough to trigger a new report. If the difference is too small, the oracle client will not send the report to the
SortedOracles
contract.
The last check will not be moved, as this is just an optimization for the oracle client, and authorized accounts should be able to report as often as they like. The first two checks will be moved on-chain to be performed in a trustless and transparent manner. Moving these checks on-chain will support a move to a decentralized oracle setup which eliminates the single failure point and contributes to providing Mento stablecoin users with a strong guarantee of price data availability, among other advantages.
This proposal, however, will focus only on moving the first check for price deviation on-chain. An on-chain circuit breaker will be implemented in a follow-up proposal which will cover the second check.
Specification
Overview
The SortedOracles
contract will be amended to include a new modifier, checkReport(address token, uint256 value)
. The modifier will be added to the report function. A reference to a new contract, ReportFilter
, will be added to SortedOracles
. The responsibility of the new contract will be to check a specified price report meets all conditions before the SortedOracles
contract processes the report. When an oracle client calls the report function, the ReportFilter
will return a bool indicating whether or not the specified report meets all conditions. If the report doesn’t meet a condition, it will not be taken up by the SortedOracles
contract. FilterCondition
contracts each have a single responsibility, the same interface and will be manageable through the ReportFilter
. A new filter condition contract, PriceDeviationFilter
, will be created to check that a given report does not deviate more than the maxPercentageDeviation
when compared with the existing reports. The maxPercentageDeviation
will initially be set to the value currently used in the oracle clients but can be changed by governance.
Rationale
The design follows a modular approach to give us flexibility with the option to add additional filter conditions at a later date without redeploying SortedOracles or ReportFilter. The ReportFilter only needs to store a mapping of enabled filters and their addresses. The logic for executing the checks should not need to change as all filters will implement the same interface.
Caveats
This implementation will increase the gas cost for each report submitted by oracle clients. With each new condition added, the gas cost will increase further. This increase is an unfortunate effect but necessary.
Technical Specification
IFilterCondition
interface:
IReportFilter
interface:
Implementation
TBD
Summary of Changes:
- Create IReportFilter & IFilterCondition interfaces
- Create PriceDeviationFilter contract
- Create ReportFilter contract
- Add modifier to SortedOracles
- Update SortedOracles.report()
Test Cases
Will be included with implementation.
Security Considerations
Enabling and disabling filter conditions will be left to governance. However, this potentially leaves the system vulnerable to a governance attack. In this case, it would be possible for an attacker to disable all filters to allow a bad price to be taken up by SortedOracles. This is a low risk as cLabs still run the oracle clients. Before moving to a decentralized oracle setup, there will be other layers in place to protect the system’s integrity should this occur.