How it works
A trove's life
sequenceDiagram
participant You
participant PAR as PAR program
participant Pool as Stability pool
You->>PAR: open_trove(bucket_index, collateral, debt)
PAR->>PAR: check both oracles fresh and within 2%
PAR->>PAR: check ratio >= 120%, debt >= 200 PAR, branch under ceiling
PAR-->>You: mint debt PAR (debt + upfront fee is recorded)
PAR-->>Pool: mint the upfront fee and accrued interest
You->>PAR: set_rate(new_index) (free once a week)
You->>PAR: repay / borrow / add_collateral / withdraw_collateral
You->>PAR: close_trove: burn all debt, take all collateral backOpening
open_trove(bucket_index, collateral, debt) moves collateral of the branch's LST into the vault and mints debt PAR to your account. The recorded debt is debt plus the upfront fee: seven days of interest at the trove's own rate (UPFRONT_FEE_PERIOD_SECS), paid to the stability pool. The trove must end at or above 120% collateral, carry at least 200 PAR of debt, and the branch must stay under its debt ceiling.
Picking a rate
bucket_index picks the rate: rate_bps = 50 + 10 x bucket_index, so index 0 is 0.5% and index 245 is 25%. A higher rate costs more interest and puts you further back in the redemption line. A lower rate is cheaper and is redeemed first.
Changing the rate
set_rate(new_index) moves the trove to another bucket. It is free once every seven days (RATE_CHANGE_COOLDOWN_SECS). Sooner than that, it charges the upfront fee at the new rate, so jumping away from a redemption at the last second costs more than it saves. Only the owner can call it: the trove PDA is seeded by the owner's key and the owner must sign.
Adjusting and closing
add_collateral, withdraw_collateral, borrow and repay each re-check the 120% floor where they could lower it. close_trove burns the full debt and returns all collateral; the trove account closes and its rent returns to the owner.
Redemption: the dollar floor
sequenceDiagram
participant R as Redeemer
participant PAR as PAR program
participant B0 as Lowest non-empty bucket
participant B1 as Next bucket
R->>PAR: redeem(amount, max_fee_bps) + [bucket, trove, trove, .., bucket, trove, ..]
PAR->>PAR: fee = 0.5% floor + base rate after this redemption
PAR->>B0: take debt from its troves, pay collateral worth $1 per PAR minus fee
PAR->>B1: only once B0 is empty
PAR-->>R: collateral, PAR burnedredeem(amount, max_fee_bps) burns up to amount PAR and pays one dollar of collateral per PAR minus the fee. The remaining accounts are [bucket, trove, trove, .., bucket, trove, ..]. Each bucket must be the lowest non-empty bucket at the moment it is reached (checked against the bitmap), so a higher rate is only touched once every lower rate is fully redeemed. A listed trove that already left the bucket is skipped; a bucket listed out of order ends the walk.
The fee stays in the redeemed trove: the borrower being redeemed is the one paid. A redeemed trove keeps whatever collateral is left over and its debt shrinks by the PAR burned against it.
Because anyone can always swap 1 PAR for $1 of collateral, PAR trading under a dollar is an arbitrage that pulls it back up.
Liquidation
A trove whose collateral is worth less than 120% of its debt can be liquidated by anyone with liquidate:
- Interest is accrued first, so it goes to the depositors who held the pool before the liquidation.
- The liquidator earns 0.5% of the trove's collateral, capped at two whole tokens.
- The stability pool burns PAR against as much of the debt as it can absorb, and takes collateral worth at most 105% of what it burned.
- Any debt the pool cannot cover is redistributed over every other trove in the branch, with collateral worth at most 110% of that debt.
- Collateral beyond those caps stays claimable by the trove's owner through
close_trove.
flowchart TD
L[liquidate] --> A{ratio < 120%?}
A -- no --> X[TroveHealthy error]
A -- yes --> R[0.5% of collateral to the caller, max 2 tokens]
R --> P{pool can absorb?}
P -- all --> S[pool burns PAR, takes collateral up to 105%]
P -- part --> S
P -- part --> D[rest redistributed to other troves, up to 110%]
S --> C[surplus claimable by owner]
D --> CStability pool
provide_to_pool(amount) deposits PAR. Every liquidation shrinks deposits pro rata and pays them collateral; every instruction that accrues interest mints that interest to the pool as PAR. withdraw_from_pool(amount) withdraws (pass u64::MAX for everything, 0 to just claim gains) and always pays out the collateral and PAR earned. The math is Liquity's product/sum scheme with scale factors, so every payment is O(1) regardless of how many depositors there are.