Trove Manager (State Machine)

TroveManager developer guide — trove status state machine, branch lifecycle gates, read APIs, and event indexing

This page explains the TroveManager integration surface for developers: the trove status state machine, the branch lifecycle gates, and the most reliable ways to read state and index events.

circle-exclamation

At a glance

  • A Trove is a position; the TroveManager is the per-branch contract that tracks its accounting and enforces liquidation/redemption rules.

  • Troves have an explicit status enum (active, zombie, closedByOwner, closedByLiquidation, …).

  • Most user write flows go through BorrowerOperations; TroveManager exposes read APIs and emits events that indexers can rely on.

  • Branches can become Pending / Active / Deprecated (via CollateralRegistry config), and can enter shutdown (shutdownTime).

Where TroveManager fits

Conceptually:

  • BorrowerOperations is the primary write entrypoint for end users and integrators (“open/adjust/close”).

  • TroveManager is the branch coordinator: it stores per-trove fields, computes “latest” debt/collateral views, and executes liquidations/redemptions under protocol rules.

  • TroveNFT represents ownership of troves (ERC‑721). TroveManager mints/burns it on open/close.

spinner

Trove status enum (what each means)

In the ITroveManager interface, troves have:

Status
Meaning
Typical UI / indexer interpretation

nonExistent

Trove ID has no recorded state

Not opened (or invalid ID)

active

Normal live position

Borrow/repay/adjust allowed (subject to branch gates)

zombie

Live, but treated specially (see below)

Still your trove; can be adjusted or liquidated

closedByOwner

Closed voluntarily

Final state; NFT burned

closedByLiquidation

Closed via liquidation

Final state; NFT burned

Trove lifecycle (state machine)

spinner

The “zombie” state (why it exists, what changes)

A trove can become zombie during redemption flows when its remaining debt becomes tiny (below MIN_DEBT).

From the TroveManager implementation logic:

  • zombie is used to prevent redemption loops from being griefed by many tiny troves.

  • When a trove becomes zombie, it is removed from the SortedTroves ordering.

  • A pointer (lastZombieTroveId) can cause the next redemption to check a pending zombie trove first.

Developer implications:

  • Treat zombie as a live position, not a closure.

  • Liquidation logic treats both active and zombie as eligible.

  • UI can surface zombie as “special state after redemptions; adjust to restore normal status”.

Branch lifecycle gates (CollateralRegistry + shutdown)

TroveManager also enforces branch-level rules:

1) Collateral status gating

TroveManager queries CollateralRegistry for the collateral branch status.

High-level behavior:

Branch status
Meaning
What is blocked

Pending

Not yet active

New troves and adjustments are blocked

Active

Normal operation

Deprecated

Wind-down mode

Net debt increases are blocked (you can repay/close, but can’t increase debt)

If you build a frontend, expect reverts like CollateralStatusForbidsOperation() and display an explicit “branch is pending/deprecated” message rather than a generic failure.

2) Shutdown (shutdownTime)

TroveManager exposes shutdownTime():

  • 0 means “not shut down”

  • > 0 means the branch entered shutdown at that timestamp

Shutdown affects accounting and allowed operations. One observable behavior is interest accrual semantics:

  • before shutdown: interest accrues up to “now”

  • at/after shutdown: interest accrues at most up to shutdownTime for positions not updated since shutdown

Prefer “latest” views for user-facing numbers

  • getLatestTroveData(troveId) returns a LatestTroveData snapshot including:

    • entireDebt (includes interest accrual)

    • entireColl (includes redistribution gains)

    • accruedInterest, redistribution deltas, and rate metadata

This is usually the safest data source for showing “current debt/collateral” in a UI.

Use raw storage for status and configuration

  • Troves(troveId) returns raw stored fields (recorded debt/coll, status, rate, batch manager, …).

  • getTroveStatus(troveId) returns the status enum directly.

CR helpers

  • getCurrentICR(troveId, price) returns the current collateral ratio at a provided price.

Integrators should treat the price input as part of the contract: pass the correct branch oracle price. If you pass a different price source, the CR number is not meaningful.

Events to index (ITroveEvents)

For indexers and analytics, the most useful events are in ITroveEvents:

  • TroveUpdated(troveId, debt, coll, stake, annualInterestRate, …) — snapshot of a trove’s latest state

  • TroveOperation(troveId, operation, … deltas …) — what changed and why

  • Liquidation(...) — aggregate liquidation totals

  • Redemption(...) and RedemptionFeePaidToTrove(troveId, fee) — redemption totals + per-trove fee accounting

  • BatchUpdated(...) / BatchedTroveUpdated(...) — batch manager changes (if your deployment uses batches)

circle-info

Events can be emitted by both TroveManager and BorrowerOperations depending on the action. Index the deployed contracts’ ABIs and events rather than relying on a single emitter.

Integration checklist (practical)

  • UI / wallet integration

    • discover troves by indexing TroveNFT Transfer events

    • for each troveId, show: status + getLatestTroveData + derived CR/liquidation price in your UI

    • handle zombie explicitly (do not show it as “closed”)

    • on write failures, map common reverts to user-facing messages (branch pending/deprecated, shutdown, slippage/routing failures, …)

  • Indexer / analytics

    • treat “close” as terminal: trove NFT burn + status becomes closedByOwner or closedByLiquidation

    • use TroveOperation as your “what happened” log and TroveUpdated as your “latest snapshot” stream

    • handle batch manager events if enabled (batch shares affect per-trove debt accounting)

Next reads

Last updated