DeFi Security: Inside the Mento Protocol's Circuit Breaker
September 6 2023
by Bayo Sodimu
Introduction
Security should always be at the forefront of any design considerations when developing blockchain-based applications. This is particularly true in Decentralized Finance (DeFi), where protocols often manage large volumes of funds, making them potential targets for various attacks. In the context of addressing potential malicious attacks, it’s critical to understand and manage risks at multiple levels. Take, for instance, the role of oracles within the Mento protocol. Oracles are third-party services that supply smart contracts with external data, which might not be readily available on a blockchain. For the Mento protocol, oracles provide an up-to-date and accurate price feed of exchange rates of a given token against various currencies. This data enables the protocol to maintain the peg of our stable assets. However, this dependency on oracles also presents its own set of risks, including possible manipulation attacks and the fallout from extreme market volatility. If these risks were to materialize, the Mento Reserve could be at risk during periods of severe price turbulence.
The inherent risks in DeFi highlight the importance of implementing robust safeguard mechanisms within protocols. We've implemented an automated on-chain circuit breaker, providing an added layer of security for our protocol against abrupt price fluctuations and potential manipulation tactics.
In this post, we'll delve into the design and implementation of the Mento protocol circuit breaker and touch on the vital role these mechanisms can play in fortifying the DeFi landscape.
Understanding Circuit Breakers
Before diving into the specifics, it's crucial to understand what we mean by a "circuit breaker". The term stems from a design pattern that gained popularity during the rise of the microservices architecture in software engineering. The circuit breaker pattern was primarily utilized to prevent cascading failures across interconnected systems, preventing any single malfunction from spiralling into a system-wide collapse.
The concept of a circuit breaker isn't exclusive to software engineering; it's also used in traditional financial (TradFi) stock markets. In this context, a stock market circuit breaker serves as a safeguard that temporarily halts trading activities in response to significant price movements, acting as a buffer against extreme volatility. Therefore, it's essential to acknowledge that a "circuit breaker" is not a concrete object but rather a versatile pattern or mechanism designed to enhance the resilience of a system, whether it is a software system or a financial market.
TL;DR
The Mento Circuit Breaker temporarily halts or can limit trading under abnormal market conditions. It's controlled by a smart contract called the BreakerBox, which works with two other smart contracts that manage virtual asset pools and store exchange rate reports. The BreakerBox holds collections that store essential data, like the trading mode for each exchange rate feed. Abnormal conditions that require a change in trading mode are detected by contracts called 'Breakers'. Once a breaker is triggered, trading will be halted or limited. An automated reset mechanism is built in, allowing trading to resume after the market conditions have returned to normal. Such a system aims to combat price manipulation, preserve market integrity, safeguard users' assets, ensure financial stability, and encourage regulatory compliance. Adopting resilient mechanisms like circuit breakers can potentially strengthen the security of the DeFi ecosystem.
So How Does The Mento Circuit Breaker Work?
The Mento Protocol’s circuit breaker aims to shield the protocol by swiftly detecting unusual market conditions and responding by suspending or halting trading. Once stability returns, it ensures that normal operations are re-established. The BreakerBox, a core smart contract, controls the operations of the circuit breaker.
The BreakerBox
As the command centre for the circuit breaker, the BreakerBox is responsible for overseeing all operations and maintaining the necessary state for its functioning. It interfaces with two core smart contracts within the protocol: the BiPoolManager, which manages virtual asset pools, and the SortedOracles contract, which stores the exchange rate reports provided by oracle clients.
Each exchange rate feed is associated with a unique identifier, the rateFeedId
, used as a reference throughout the protocol to access information related to that specific exchange rate/rate feed. Importantly, each asset pool managed by the BiPoolManager
is linked to a single rate feed that is used to dictate the price that the pool follows. It’s worth noting that multiple virtual asset pools can use the same rate feed.
Within the BreakerBox
, there are numerous mappings that store essential data. One key mapping, rateFeedTradingMode
, deserves particular attention as it stores the current trading mode of each rate feed.
In the context of the circuit breaker, a trading mode is represented by a bitmask - a binary value that signifies the constraints applied to trading during certain market conditions. Currently, there are four modes:
- Bidirectional (00)
- Inflow trading blocked (01)
- Outflow trading blocked (10)
- Trading halted (11).
These bitmasks are especially useful as they allow for the simple and efficient aggregation of trading modes using bitwise operations. By applying such operations, the system can combine the constraints imposed by multiple market conditions on trading, facilitating a precise and responsive regulation of trading activities.
Detecting Abnormal Conditions
A key function of the circuit breaker is the ability to detect conditions that should require a change in the trading mode of a specific rate feed. These conditions are stored within individual contracts called 'breakers'. Each breaker holds the logic and any associated state variables necessary to evaluate whether it should be triggered for a given rate feed at any point in time. All breakers inherit from a common interface, the IBreaker
, which specifies a method, shouldTrigger()
.
The shouldTrigger()
method is a key part of the breaker logic, as shown in the snippet below from the MedianDeltaBreaker. This function determines whether a breaker should be triggered based on the defined logic. Specifically, the MedianDeltaBreaker
checks if the median rate for a rate feed has changed beyond a certain threshold compared to its previous state.
Below is a breakdown of the function:
- The function first determines if this is the first time the rate feed is being checked. If so, it saves the current median rate as the initial Exponential Moving Average (EMA) and returns 'false'. This means that, at this point, there's no need to trigger the breaker.
- If there's an existing EMA (i.e., this isn't the rate feed's first check), the function calculates a new EMA. It considers the current median rate, the previous EMA, and applies a smoothing factor to weigh these values. The calculated EMA is then saved for future reference.
- Lastly, the function checks if the gap between the previous EMA and the current median rate is greater than a set threshold. If the difference is too significant, it returns 'true', signalling the breaker should be triggered.
The BreakerBox
, for its part, holds references to all the breakers and monitors the results of their evaluations. Each time a rate feed report is added or removed, the BreakerBox
checks the conditions of all linked breakers for the rate feed.
Responding to a Triggered Breaker
The BreakerBox
contract maintains a mapping, breakerTradingMode
, that stores the trading mode to be activated when a particular breaker is triggered. When a breaker is triggered for a rate feed, the trading mode for the breaker is updated in the mapping rateFeedBreakerStatus
, along with a timestamp indicating when the breaker was triggered.
As a result, a rate feed can be associated with various trading modes, each corresponding to a different breaker. However, the rate feed is ultimately guided by a single trading mode at any given time. This trading mode is determined by aggregating all currently applicable trading modes through a bitwise OR operation.
So as an example, if we have one rate feed that has trading modes, bidirectional (00) and inflow blocked (01) set by two different breakers, we can determine its overall trading mode by applying a logical OR operation to the bit masks representing the trading modes.
Bidirectional trading (00) + Inflow blocked (01) = 00 | 01, which results in 01, signifying that the overall trading mode, given the current market conditions, is inflow blocked.
Taking a broader view, we can observe the relationships between pools, rate feeds, trading modes and breakers as illustrated below.
A pool must be linked to a single rate feed, but many pools can have the same rate feed. Each rate feed is linked to a single trading mode, and several rate feeds can have the same trading mode. Additionally, each trading mode can be associated with one or more breakers.
The BiPoolManager
queries the BreakerBox
to determine the current trading mode for the RateFeedId of a pool by invoking the getRateFeedTradingMode function. This is done prior to executing any swap, ensuring that trading hasn’t been halted for pools referencing that particular rate feed. If trading has been halted due to a breaker being triggered, the transaction will be reverted. This is illustrated in the code snippet below.
While the circuit breaker has been designed to support trade direction limitations, this feature is not yet implemented in the BiPoolManager
. Any trading mode that is not 'bidirectional trading' (00) will halt trading. A future update to the BiPoolManager
is planned to integrate and support these more granular trade control capabilities fully.
Resetting a Triggered Breaker
Once a breaker has been triggered for a rate feed, trading can only resume after the breaker has been reset for that specific rate feed. To streamline this process, the circuit breaker features automated reset logic that is triggered when rate reports are either added or removed, negating the need for manual intervention.
This automated reset process follows a two-stage approach: it starts with a cooldown period, followed by an evaluation of the reset conditions specific to that breaker.
Each breaker maintains a mapping that specifies a cooldown period for each distinct rate feed. This cooldown period represents the minimum time that must elapse since the breaker was triggered before a reset is allowed.
In certain scenarios, an automated reset may not be ideal, and instead, a manual reset triggered by governance may be more desirable. This can be achieved by setting the cooldown time for the rate feed to zero. Doing this will require a manual reset of the breaker for this particular rate feed, which can only be accomplished by invoking the setRateFeedTradingMode function.
The flowchart below illustrates the steps involved in the reset process, from the beginning of the cooldown period to the eventual reset of the breaker.
After the breaker has been successfully reset for a rate feed, trading will resume as normal.
Drawbacks of the Current Implementation
Whilst the current implementation has the potential to contribute to the security of the protocol, like all systems, it is not without its shortcomings:
- Increased Gas Usage: The circuit breaker mechanism, which requires frequent smart contract interactions and constant reading and writing of storage upon Oracle reports and trade initiations, greatly increases the gas consumed by transactions. However, the majority of these gas costs are absorbed by Oracle clients.
- Risk of Breaker Manipulation: The mechanism's reliance on breaker contracts to detect abnormal market conditions introduces the risk of manipulation. Malicious actors could get breakers to trigger artificially, leading to unnecessary trading disruptions.
- Manual Override Misuse: The manual override is a secondary precaution during severe market disruptions but also opens the door for potential exploitation. Malicious actors gaining significant voting power could misuse this feature to halt trading—a scenario known as a governance attack. However, it's worth noting that the risk of this occurrence is likely low, as other, more critical features within the protocol could serve as more attractive targets for a governance attack.
Future Enhancements
The current circuit breaker implementation addresses our immediate needs and was designed with extensibility in mind, so we're constantly looking towards the future. We have several planned enhancements and improvements in store. Key improvements include the introduction of an accumulating cooldown mechanism and comprehensive support for unidirectional trading. These innovations will further protect the system against potential vulnerabilities, ensuring the continued security and integrity of the protocol.
The Role of Circuit Breakers in Strengthening DeFi
Circuit breakers can serve as a significant line of defence within the DeFi landscape, providing protection and stability in several ways:
- Combatting Price Manipulation: By halting trading during instances of extreme volatility, circuit breakers safeguard DeFi protocols from potential market manipulation.
- Preserving Market Integrity: Circuit breakers introduce necessary pauses in chaotic market conditions, allowing participants to recalibrate and promoting a more orderly market environment.
- Safeguarding Users’ Assets: Circuit breakers help protect traders and liquidity providers from sudden market downturns, fostering increased trust and participation in DeFi.
- Ensuring Financial Stability: Circuit breakers can prevent cascading liquidations during market stress, contributing to the overall financial stability of DeFi.
- Encouraging Regulatory Compliance: As DeFi comes under increasing regulatory scrutiny, implementing risk mitigation measures like circuit breakers demonstrates a commitment to secure operations.
Conclusion
The proposal of EIP 7265 represents an important stride in enhancing the security landscape within decentralized finance by setting a standard for circuit breaker implementation. However, these mechanisms are just one part of a comprehensive safety blueprint needed for DeFi protocols.
By incorporating lessons from traditional finance and software engineering, we can continually bolster the resilience of the decentralized finance space. Transparency and knowledge sharing can only further solidify this evolution.
The Mento circuit breaker illustrates the potential that resilience-focused mechanisms bring to the DeFi sector. As a decentralized, transparent, and automated mechanism, it helps ensure security without giving Mento Labs undue control over trading operations. This hands-off approach underpins the principles of decentralized finance. As we look forward to the broader community’s adoption and refinement of these security practices, we remain optimistic about the collective efforts that will fortify DeFi's ongoing stability and integrity amidst continuous evolution and growth.
Discover more
Sign up for
Mento Magazine
Want to know more about Mento?
Introducing Mento Magazine, featuring
news and updates on the Mento platform
and Mento Labs