Skip to main content
A circuit breaker rejects a candidate transaction when its configured condition is met. The policy must identify the custody address, measured asset, observation period, and permitted operations. A rejected transaction does not itself set a persistent pause flag in your protocol.

Choose the measured condition

Use the Balancer example for a concrete shared-custody policy, or the ERC-4626 example to combine flow limits with operation checks.

What a cumulative limit measures

A cumulative watcher measures one ERC-20 balance at the assertion adopter. The executor records block buckets and compares directional net flow with the balance baseline for the retained window, exposed as tvlSnapshot. For outflow, incoming tokens offset outgoing tokens. For inflow, outgoing tokens offset incoming tokens. The limit is not a sum of gross transfers, a USD valuation, or the protocol’s reported totalAssets(). The callback runs when net flow is strictly greater than the configured basis-point threshold. It decides whether to reject. The simple hard-breaker examples always revert when invoked. For a 100,000-token baseline and a 1,000-bps outflow threshold: As old buckets expire, both the retained flow and its baseline can change. A new budget can therefore become available without an administrative reset. Choose the window around the time your team needs to investigate and act.

Match the custody boundary

A watcher on a pool address cannot measure assets held by a different vault. A watcher on a shared vault combines flows from its pools. Strategy deposits can look like outflow from idle custody even when total portfolio value is unchanged. Use the actual ERC-20 and custody addresses, and test the token’s transfer behavior. Native ETH, rebases, external strategies, and asynchronous settlement need an accounting model that represents those movements. A threshold does not by itself guarantee a maximum loss.

Bucket ingestion and balance reconstruction

The executor ingests completed canonical blocks using ERC-20 transfer logs and post-block balances. Ingestion can lag block building. During evaluation, missing history is reconstructed from the difference between the latest recorded balance and the candidate’s pre-transaction balance, spread across the missing blocks. These reconstructed buckets are temporary; canonical ingestion supplies the durable history. The reconstructed gap preserves its total net balance change. It cannot recover offsetting transfers or their exact timing. If the gap crosses the rolling cutoff, its allocation between expired and retained buckets can also differ from the original history. Do not treat gross-flow or rate context as an exact replay when history was reconstructed. The rate reference gives the field definitions and formulas.

Test the condition and dispatch separately

A callback test can prove that the assertion rejects a particular context. It cannot prove that the executor invokes the callback at the correct rolling threshold. Local pcl test does not simulate cumulative window dispatch. Use an executor-backed environment for multiple transactions, threshold equality, opposite-direction flow, expired buckets, and zero balance baselines. Test legitimate strategy movements and emergency operations alongside violating transactions. A tiered policy must prove that an exception caused the allowed effect; the presence of a liquidation call alone is insufficient.

Monitoring and incident response

Choose limits from observed protocol activity and the scenarios your team needs to stop. Backtest them, then exercise the policy on a replica of your protocol on an Ethereum fork in alerting. Your FDE can help distinguish intended transactions from rejections that require policy changes. Configure Slack alerts and use the rejection details to investigate before earlier flow ages out of the window. Threshold changes and release updates remain subject to your team’s signing authority.