Documentation

How halts work

The five-state machine that gates every risk-increasing action.

The five states#

Every market sits in exactly one state at a time, held by its own HaltController. The state decides which actions the market will accept.

StateSupply / BorrowLiquidateRepayInterest
OPENYesYesYesAccruing
HALTINGNoNoYesAccruing
HALTEDNoNoYesFrozen
RESUMINGNoNoYesAccruing
SETTLINGNoNoYesFrozen

Repayment is available in all five. That is deliberate and it is the single most important row in the table: a borrower must never be trapped in a position they are trying to get out of.

Why there are five and not two#

A plain on/off switch would be enough to stop the damage, but not enough to reopen safely. The extra states exist to handle the edges of a halt rather than its middle.

HALTING

A corporate action is known to be coming. New borrowing and new supply stop before the price actually goes bad, rather than after. Nobody gets to open a fresh position into a window that is about to become unpriceable.

RESUMING

A fresh price has arrived, but liquidations do not reopen in the same instant. If they did, every position that drifted underwater during the freeze would be liquidatable at once, at a price borrowers had no opportunity to react to. RESUMING is a grace window: the price is live, repayment and top-ups work, and only then do liquidations come back.

SETTLING

The terminal case, covered in full on Settlement. It exists so that a halt which never resolves cannot trap lender capital indefinitely.

How a halt is detected#

The oracle exposes a pause flag. Anyone can call sync() on a market's halt controller, which reads that flag and moves the state accordingly. It is permissionless on purpose: the protocol should not depend on a privileged keeper noticing in time.

Separately, every price-dependent function checks freshness directly against maxOracleStaleness, currently 24 hours. This matters because the halt controller only updates when somebody calls sync(), so it can still report OPEN while the underlying feed has gone stale. The independent check means a stale feed blocks borrowing even if nobody has synced yet.

How the corporate action itself is spotted#

This is the honest soft spot, so it is worth stating plainly rather than glossing. Today the event is spotted by a human. Somebody calls pauseOracle() through the multisig, and from that point everything is trustless: anyone can call sync() to propagate it, so nobody can sit on a halt once the feed is paused.

One layer is genuinely automatic regardless. The staleness check blocks borrowing on a feed that has stopped publishing whether or not anybody noticed or synced. Its limitation is precision rather than reliability: a stale feed cannot be distinguished from a weekend.

The route to automating detection exists and is not hypothetical. CF Benchmarks publishes an xStocks corporate action feed with a two-stage Pending then Effective lifecycle, which maps onto HALTING and RESUMING almost exactly. It is an off-chain data product, so bringing it on-chain still needs a keeper: that moves the trust from a human watching the news to a keeper watching a regulated feed, which is better without being trustless.

HaltGate is the response, not the detector

Detection and response are separate problems. Several vendors sell detection. What this protocol implements is what a lending market should actually do once a price cannot be trusted, which is the part that is deployed, tested and verifiable on-chain. The detector is a swappable input.

Worth knowing: not every corporate action needs a halt at all. xStocks handles splits and dividends through a rebasing multiplier, so a two-for-one split doubles token balances while halving the price and passes through cleanly if a protocol reads both consistently. The window a halt actually protects is the narrower one where price and multiplier disagree.

Two layers, on purpose

The state machine is the deliberate, observable signal. The staleness check is the backstop that does not depend on anyone doing anything. Either one is enough to stop a borrow.

What freezes, and why interest is one of them#

Interest freezes in HALTED and SETTLING only, not in every non-OPEN state. The test is whether a trustworthy price exists. In those two there is none, so a borrower cannot judge their own position, cannot be liquidated, and would be accruing debt against something they are locked out of managing. The borrow index stops advancing and resumes from exactly where it left off.

HALTING and RESUMING keep accruing. In both, the price is still usable: HALTING is a pre-warning before the feed goes, and by RESUMING a fresh price has already landed. A borrower can repay or top up in either, so the loan is genuinely live and charging for it is fair.

The consequence for lenders is that yield pauses whenever interest does. That is the honest trade: the same event that protects borrowers from a bad liquidation also stops the meter for the people funding them.

What a halt does not do#

  • It does not seize anything. No position changes hands because of a halt.
  • It does not cancel debt. Balances are exactly where they were when the halt began.
  • It does not affect other markets. Each stock has its own controller, so halting NVIDIA leaves Tesla, Apple, Microsoft and the S&P 500 market untouched.
  • It does not block repayment, and it does not block repaying a fixed-term loan either.