This standard outlines a smart contract interface for a Circuit Breaker that triggers a temporary halt on protocol-wide token outflows when a threshold is exceeded for a predefined metric. This circuit breaker does not assume the structure of the underlying protocol, and mainly serves as a pass-through vehicle for token outflows. In order to maintain correct internal accounting for integrated protocols, and to provide maximum flexibility for developers, developers can specify if the circuit breaker contract should delay settlement and temporarily custody outflows during the cooldown period, or revert on attempted outflows.
ethereum:master
← DeFi-Circuit-Breaker:master
opened 06:55AM - 03 Jul 23 UTC
This standard outlines a smart contract interface for a Circuit Breaker that tri… ggers a temporary halt on protocol-wide token outflows when a threshold is exceeded for a predefined metric. This circuit breaker does not assume the structure of the underlying protocol, and mainly serves as a pass-through vehicle for token outflows. In order to maintain correct internal accounting for integrated protocols, and to provide maximum flexibility for developers, developers can specify if the circuit breaker contract should delay settlement and temporarily custody outflows during the cooldown period, or revert on attempted outflows.
- Example implementation of a circuit breaker
- Interface
- 'ProtectedContract' Contract to be inherited by DeFi contract for CB best practices
Implementation/ testing:
We would love some feedback on this proposal!
2 Likes
In onTokenOutflow
it says:
Before calling this method, the protected contract MUST transfer the EIP-20 tokens to the circuit breaker contract.
Have you considered instead having the protected contract approve the tokens and the circuit breaker using transferFrom
? This would be more efficient if there’s no rate limit because the circuit breaker can transfer directly from the protected contract to the recipient.
Edit: It turns out this doesn’t really improve net gas costs, and it relies on a larger refund which might be better to avoid, so I think two transfers is good.
1 Like
Thanks for validating this!
Excited to getting this PR merged. It will allow for increased modularization of the CircuitBreaker.
DeFi-Circuit-Breaker:core-overhaul
← ikigai-labs-xyz:new-architecture
opened 02:42PM - 17 Aug 23 UTC
# Add DSM implementation and modularize CircuitBreaker
@vdaubry and me have b… een working the past few weeks to implement the new CircuitBreaker specifications and optimize modularity. We believe the EIP should provide a modular standard for anyone to extend upon and build individualized implementations.
The main characteristic of hacks is “liquidity being drained in a short time frame”. That’s why it makes sense to track that metric on-chain and introduce a CircuitBreaker standard to provide a way to handle unusual TVL activity. Nevertheless, there are multiple other metrics that are also highly indicative of hacks, most and foremost unusual price changes within AMM’s or other protocol specific values that should not be able to change by unrealistic amounts under normal circumstances.
That lead us to our conclusion: The CircuitBreaker standard should provide a way to track **multiple** metric**s** on-chain. It might be token outflows, but it should also enable protocols to track other metrics, that are crucial for protocol health. Protocol’s should not be bound to only tracking TVL.
Furthermore, that will allow others to build extensions on top of the CircuitBreaker for their specific needs.
Crucially, this philosophy is very common when it comes to EIP’s. Two of the most prominent, EIP20 and EIP721, both follow this philosophy: A minimalistic base implementation, that maximizes compatibility and modularization to allow others to build individualistic implementations and extensions.
## The new approach in a nutshell🥜
The new CircuitBreaker base implementation allows the protocol to configure *********************security parameters********************* (a more generic naming for tokenLimiter) for their protocol. Each security parameter has a unique `bytes32` identifier (previously a token address). This still allows protocol’s to configure it to track token addresses, but it also allows protocols to track other metrics. Each security parameter also has to be configured with a `SettlementModule` contract. This contract gets called to “settle” transactions whenever the CircuitBreaker gets triggered. The CircuitBreaker will automatically call the `prevent` function of the SettlementModule. It is up to the SettlementModule implementation to specify what will happen. The prevent function can be coded to always revert, schedule a future transfer (delay the settlement) or do something else. This allows protocols to implement highly individualistic settlement strategies for different metrics. Delaying the transfer or reverting are not the only options anymore. Protocol’s could also choose to let governance settle the transactions or implement other settlement strategies.
**And the cool thing about this:** Our proposed approach is perfectly capable of doing the exact same thing as the original CircuitBreaker did beforehand: It can track token in- & outflows and delay or revert potential hack transactions. Even the same, existing Foundry tests pass with our proposed approach.
To summarize: We are just modularizing the CircuitBreaker to allow for more customization. It still achieves the existing goals of delaying or reverting transactions.
## What has been changed
Our code changes followed the philosophy of introducing minimal code changes to the existing code, while still implementing our new approach.
### **EIP7265 Interface**
- Renamed `AssetRegistered` event to `SecurityParameterAdded`
- Renamed `AssetInflow` event to `ParameterIncrease`
- Renamed `AssetWithdraw` event to `ParameterDecrease`
- Renamed `AssetRateLimitBreached` event to `RateLimited`
- Renamed `registerAsset` function to `addSecurityParameter`
- Renamed `updateAssetParams` function to `updateSecurityParameter`
- Renamed `onTokenInflow` function to `increaseParameter`
- Renamed `onTokenOutflow` function to `decreaseParameter`
- `onNativeAssetOutflow` function is being handled by `decreaseParameter`
- Deleted `overrideRateLimit`
- became redundant because of `SettlementModule` implementation
- Deleted `overrideExpiredRateLimit`
- became redundant because of `SettlementModule` implementation
### **CircuitBreaker.sol**
This is the new base CircuitBreaker implementation. The new contract only has 236 lines instead of 349 and allows for more modularization.
**Changes**
- Implemented more generic naming
- tokenLimiters mapping uses `bytes32` as the key instead of an address
- Renamed “tokenLimiters” to “limiters”
- Implemented OpenZeppelin `Ownable` for more security when it comes to admin handling
- Deleted gracePeriod
- No longer needed
- Deleted global isRateLimited variable
- Rate Limiting is now being handled on a per security parameter basis. If protocol’s choose to implemented global rate limiting, they can do so by checking the status of a given security parameter limiter.
- New `_decreaseParameter` and `_increaseParameter` functions call the prevent function on the SettlementModule in case of the CircuitBreaker being triggered. The prevent function implementation then specifies how to handle the trigger situation, as opposed to locking the funds by default.
- Deleted `_safeTransferIncludingNative`
- Is no longer needed
### **New: ISettlementModule.sol**
The interface defines generic method for a Settlement module. We provided 2 sample settlement modules:
- DelayedSettlementModule
- RejectSettlementModule
Protocol can choose which SettlementModule to attach to each security parameter they’re tracking.
But protocol's can also provide their own SettlementModule if they need to.
- Renamed “schedule” into “prevent”: each module will have a different way of preventing a transaction from going through. Some module are not scheduling, such as “RejectSettlementModule”.
### **New: IDelayedSettlementModule.sol + DelayedSettlementModule.sol**
This implementation is a thin wrapper around OpenZeppelin TimelockController. The DelayedSettlementModule prevent transaction from going through by locking funds in a TimeLock. Funds can be unlocked by the “execute” function.
### **New: ITokenCircuitBreaker.sol**
This interface implements the existing event and function naming of the EIP for the TokenCircuitBreaker extension.
### **New: TokenCircuitBreaker.sol**
This contract is a wrapper for the CircuitBreaker contract. This wrapper allows for implementing the existing core functionality: Tracking asset inflows and outflows. It showcases how our proposed new CircuitBreaker contract can be extended with only minimal changes to allow for the same functionality.
1 Like
Hey, I really like the EIP and the concept of limiters is very promising.
I got a question after taking a quick look. I noticed there’s an AssetRegistered
event for the registerAsset
function:
event AssetRegistered(address indexed asset, uint256 metricThreshold, uint256 minAmountToLimit);
However, there’s no counterparty for the updateAssetParams
, which means that an indexer would be able to know the initial parameters of a registered asset but won’t be able to track further updates. Is this intentional or am I missing something?