# A circuit breaker anyone may pull, but only by proving insolvency on-chain

> Canonical: https://blazephoenix.xyz/learn/permissionless-circuit-breaker
> License: CC BY 4.0 (attribution + link) · © 2026 BlazePhoenix
> Updated: 2026-08-13



Every protocol that can be halted faces the same dilemma stated two ways. A pause button held by the team is a trust assumption: the strongest claim the system can make is that the holder will not misuse it. A pause button held by everyone is an attack: griefing costs one transaction. Almost all deployed designs pick the first and describe it as prudence.

The staking contract carries a third option. It can be halted by anybody — there is no role attached to the call — and what gates the call is not who you are but whether a specific condition currently holds on-chain: that the contract's actual token balance has fallen below what it owes. A caller either can prove insolvency or they cannot, and no amount of standing changes that.

## Why the gate cannot be spoofed

Both sides of the comparison are read from chain state inside the frame that performs the check. Holdings are the token balance of the contract, read from the token. Obligations are recomputed from storage rather than accepted from calldata. Nothing is asserted by the caller, so there is nothing for the caller to lie about — the call either finds the condition true when it evaluates it, or it reverts.

The asymmetry that makes this safe against griefing is the more interesting half. The only direction an outsider can push the balance is upwards: anyone can donate tokens to the contract, and doing so can prevent the condition from holding but can never create it. There is no public operation that removes value from the contract without a matching reduction in what it owes. So the breaker is not a lever an attacker can pull at a moment of their choosing; it is a statement about the world that either is or is not currently true, and an attacker who could make it true has already done something worse than pause the protocol.

```
halt()  is callable by any address, and succeeds iff

        balance(token, this)  <  owed(state)          read in-frame, both sides

anyone can push the left side UP  (donation)   -> can prevent, never create
no public path pushes it DOWN without reducing the right side by the same amount
```

## What tripping it does, and what it deliberately does not

When it trips, the breaker moves no funds. It pauses the protocol and opens every user's individual exit — which is the correct pairing, because a halt that locked users in while the contract was known to be short would convert an accounting problem into a confiscation. The exit returns stake minus debt.

And it cannot be quietly undone. The administrative call that lifts an emergency reverts while the breach still holds, so the operators can only cancel it by first making the contract solvent again. That is the property that distinguishes this from a pause with extra steps: the operator can build, but cannot override. The design converts a governance question — should we be paused? — into a proof obligation, and the obligation runs against the operator rather than against the user.

Finally, the two ways an emergency can begin are distinguished permanently in the log: the event carries a flag saying whether it came from the permissionless proof or from the guardian's discretion. Nobody can later describe a discretionary halt as a proven one, and nobody has to take our word for which it was.

## The companion power, which is not proof-gated at all

The article would be marketing if it stopped there, because the same contract carries the strongest privileged power in either codebase, and it sits right beside the breaker. A guardian role may declare an emergency at its own discretion, with no on-chain condition required. While it stands it disables staking, withdrawing, claiming, borrowing and repaying, and only the same key can lift it.

What that power cannot do is take principal: the emergency exit path remains open throughout and pays out stake minus debt, and the protocol's own reserve withdrawal is bounded and hard-wired to a treasury address fixed at construction. So the guardian holds a power that punishes its own holder — it strands the protocol and frees the users — but it is a power, and it is the reason a staker's lock is not unconditional. Locks run from ninety days to seven years; in front of a commitment that long, a discretionary door that opens for everyone at once is a material trust assumption, and describing the lock as structural would misstate the guarantee a staker actually receives.

One further edge belongs in the same paragraph rather than a footnote. The emergency exit does not settle outstanding rewards first, so unclaimed rewards are forfeited by taking it. Liquidation, by contrast, settles rewards before it acts. A user leaving through the emergency path should claim first if claiming is available.

## Role separation is a deployment-time property, not a code property

Both the administrative role and the guardian role are granted to the deployer. Unless they are separated at deployment time, the account that can declare an emergency is the same account that can do everything else, and the intended two-key design collapses into one. That is a configuration property rather than a code defect — which is precisely why it belongs in a threat model rather than a bug list, and why a reader evaluating a live deployment should check the two role holders on-chain rather than reading this article.

The generalisation is worth stating because it applies far beyond us: a separation-of-powers argument that depends on a deployment transaction is only as strong as the record of that transaction. If the two addresses are not independently verifiable, the design is a description of intent.

## Why the breaker's own gate has a blind spot

A proof-gated mechanism is only as good as the expression it proves, and this one has a documented weakness that we would rather state than have found. The obligations side of the comparison is computed with saturating subtractions. Saturating arithmetic collapses an entire region of state onto a single value, and the region it collapses here is the inverted one: if obligations exceed what is recorded against them, the computation floors at zero rather than going negative.

The consequence is exact and unpleasant. In precisely the state the breaker exists to detect — deep insolvency of a particular shape — the obligations term can read zero, and a comparison against zero passes trivially. One of the disclosed findings has this signature: an underwater exit that reduced total debt without recording the bad debt it left behind, creating a phantom liability that both locks a hard breach and makes the cancellation path unreachable. That is a vacuity failure rather than a silence failure — the guard is invoked, evaluates, and is satisfied for a reason unrelated to the property — and it is a distinct category worth keeping separate in any audit vocabulary.

The finding is fixed and pinned by a regression test that fails against the vulnerable contract rather than merely passing against the fixed one. The structural lesson is not fixed and probably cannot be: an invariant expressed with saturating arithmetic carries a fibre it did not intend, and the fibre is usually over the pathology.

## What remains trusted after all of this

A trustless claim from someone who cannot enumerate their exceptions is worth nothing, so: the guardian's discretionary emergency remains, as does the pause under which repayment and withdrawal stay open, the curated venue registry on the routing side, the curated list of intermediate tokens, the treasury destination fixed at construction, and the token itself. Powers can be permanently surrendered — the flag is written true at exactly one site, never written false, with no proxy and no selfdestruct through which the code could be replaced — and even then the surrender is not total: on the routing side the ability to add a venue or an intermediate survives renunciation while the ability to remove one does not, so anything added afterwards is permanent.

What a user need not trust is anyone to keep the protocol solvent, or to let them out. Those two are held by arithmetic. The distinction this article is about is the difference between that sentence and the much commoner one it resembles, which is that a team promises to be watching.

**Verify it yourself:** check the two role holders on the live deployment before relying on the separation, and confirm for yourself that the cancellation path reverts while a breach holds — the halt condition itself is a pure read of chain state, so you can evaluate it with an eth_call at any block

Related: https://blazephoenix.xyz/learn/proof-of-solvency · https://blazephoenix.xyz/learn/ungovernable · https://blazephoenix.xyz/learn/what-a-conservation-guard-cannot-see
