Skip to content
Developers

Events

What each module emits, and what an indexer should do with it. Every state transition emits, which is what makes a protocol with no administrator auditable.

Spec v0.9.1, reviewed 2026-09-08

Every state transition emits an event. That is a design rule rather than a convention: with no administrator to ask and no upgrade to inspect, the log is the only account of what happened, and an indexer built on it can reconstruct the whole history of a branch.

Positions

Emitted by each Branch.

EventWhat it carriesWhat an indexer does
PositionOpenedOwner, collateral, debt, rateOpens a position record
PositionAdjusted(user, collDelta, debtDelta, newDebt)Signed deltas and the resulting debtUpdates it. A zero resulting debt closes it
RateChanged(user, rate, fee)The new rate and any fee chargedUpdates the rate and the position in the queue
InterestMinted(amount)fyUSD minted at this accrualAdds to the branch's cumulative interest
InterestClockPaused(since) / InterestClockResumedWhen accrual stopped and restartedMarks the interval as unbilled
SurplusClaimedOwnerCloses a residual collateral claim

Interest is not emitted per position. A position's debt is a function of its recorded debt, its rate, the branch interest clock and the redistribution index, so an indexer that wants a per-position balance recomputes it rather than summing events.

Liquidation and loss

EventEmitted byWhat an indexer does
Liquidated(user, debtRepaid, collSeized, bonusWad, priceUsed, regime, mode)BranchRecords the execution with the regime and the price it used, which is what makes a liquidation checkable after the fact
Redistributed(debt, coll, L_debt, L_coll)BranchMarks every open position on that branch as carrying a share. Notify each owner with the new ratio
BadDebtRecorded(amount, cumul)BranchUpdates the branch's cumulative bad debt, which is what locks its ladder
BadDebtCovered(amount)BranchReduces the outstanding shortfall
MintFreeze(bool, tcr)BranchToggles the branch's borrowing state

Risk

Redistributed is the one event an interface must act on immediately. Positions that were healthy a block earlier now carry more debt and more collateral, at a lower ratio, without their owners having done anything.

Caps, activation and closure

EventMeaning
Activated(at)A dormant branch passed all eight criteria and is now lending
CapTierReached(index, cAbs)The branch climbed a step of its debt ladder
CapTierLocked(index, badDebtCumul)It will never climb another. Permanent
ShutdownFlagged(at, tcr)The one-hour clock to closure has started
Shutdown(reason, lastGood, urgentFrom)The branch is closed. Urgent redemptions open at urgentFrom
Settled(user, debt, coll)A position settled after closure
UpgradeDetected(newImpl)The collateral token's implementation changed
UpgradeCleared / UpgradeExtended(until)The automatic transferability test passed, or did not
Frozen(mask, until, cumul) / LiquidationFrozen(until, count) / UnfrozenThe Closer key acted, with its consumed budget

Price

Emitted by each OracleAdapter. This is the densest group and the one an interface reads most.

EventWhat an indexer does
RegimeChanged(from, to, cause)Records the transition with its cause. Drives every rule an interface displays
AnchorAccepted(idx, roundId, price, quarantinedBefore)Records a new reference print
AnchorQuarantined(idx, roundId, price, pCompRaw)The exchange print disagreed with the live markets. Publish it
AnchorSwitched(from, to)The branch moved to its second reference
Circuit(cause) / CircuitCleared()A validity failure opened or closed
JumpEdge(until)The pool executes nothing until that timestamp
SourceExcluded(id, reason)A source went absent. Reasons: stale, unqualified, invalid ratio, saturated, reverting, or a broken peg on a vault pool
RatioSnapshot(id, ratio) / RatioOutOfBounds(id, ratio)A derived source was recalibrated, or refused
MultiplierAnomaly(m, impliedShare)The feed and the token's multiplier disagree
LiveEpoch(epoch)Every outstanding liquidation flag on the branch is void
InterestUnbilled(cumul)Cumulative seconds during which interest did not accrue

An interface that watches only one of these should watch RegimeChanged. An indexer that wants to reconstruct why a liquidation executed at a given price needs SourceExcluded and AnchorQuarantined as well.

Alongside it, V4Observer emits ObserveSkipped when a pool cannot be read or holds no liquidity at the trading price, and the pull oracle emits ReporterRenounced when one of the fixed keys withdraws for good.

Pools, the wrapper and the peg module

The Stability Pool and its wrapper follow the standard token and vault event shapes: transfers, deposits, withdrawals. Beyond those, the wrapper emits when it starts selling seized collateral, and the collateral sale emits each purchase with the discount applied at that moment.

The peg module emits its swaps in both directions, and the depeg guard opening and closing. An indexer should treat the guard as the explanation for a refused entry rather than as an error.

FBR

EventEmitted byWhat an indexer does
FbrShare(f, spRatio, fmax)InterestRouterRecords the revenue share in force and the pool health that set it
Season settledFBRDistributorFreezes the totals of that season. Allocations become computable
Buy-back executedFBRDistributorRecords the amount bought, the amount credited to stakers, and the amount burned
BurnedFBRTokenReduces total supply. The only way it ever moves
Stake, unstake request, withdrawal, cancellationsFBRTracks lots, their dates and their weights
Seizure, auction opened, bid, auction closedBackstopRecords what was taken from stakers and what was recovered

A season's allocation is not emitted per user. It is computed from the counters and the frozen totals, which is why the counters are readable rather than emitted.

The vaults

Each LPVault emits on deposit, withdrawal, recentring, harvest and checkpoint. Recentring is the one to watch: it carries the old and new centres, and it briefly changes the pool's liquidity, which can invalidate that pool's price window for half an hour.

The gate hook emits nothing. It only reverts when a party other than a vault tries to add liquidity.

What is not emitted

Two absences are deliberate and worth knowing before building an indexer.

No parameter-change event, on any contract, because no parameter can change. An indexer that watches for one is watching for something that cannot happen, and its absence is a property you can rely on.

No per-second interest event. Interest is minted at each accrual and routed in one movement. Reconstructing what a specific position owes at a specific block means reading the branch interest clock and the position's own snapshot, not summing a log.