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.
No addresses here — Contract addresses must be sourced from official deployment artifacts / on-chain registries / verified explorers.
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.
Trove status enum (what each means)
In the ITroveManager interface, troves have:
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)
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:
zombieis used to prevent redemption loops from being griefed by many tiny troves.When a trove becomes zombie, it is removed from the
SortedTrovesordering.A pointer (
lastZombieTroveId) can cause the next redemption to check a pending zombie trove first.
Developer implications:
Treat
zombieas a live position, not a closure.Liquidation logic treats both
activeandzombieas eligible.UI can surface
zombieas “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:
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)
shutdownTime)TroveManager exposes shutdownTime():
0means “not shut down”> 0means 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
shutdownTimefor positions not updated since shutdown
Read APIs (recommended for UIs and indexers)
Prefer “latest” views for user-facing numbers
getLatestTroveData(troveId)returns aLatestTroveDatasnapshot 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 stateTroveOperation(troveId, operation, … deltas …)— what changed and whyLiquidation(...)— aggregate liquidation totalsRedemption(...)andRedemptionFeePaidToTrove(troveId, fee)— redemption totals + per-trove fee accountingBatchUpdated(...)/BatchedTroveUpdated(...)— batch manager changes (if your deployment uses batches)
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
TroveNFTTransfereventsfor each troveId, show:
status+getLatestTroveData+ derived CR/liquidation price in your UIhandle
zombieexplicitly (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
closedByOwnerorclosedByLiquidationuse
TroveOperationas your “what happened” log andTroveUpdatedas your “latest snapshot” streamhandle batch manager events if enabled (batch shares affect per-trove debt accounting)
Next reads
Surface overview: Smart Contracts
Architecture map: Technical Overview
Practical checklist: Integrator Guide
Last updated