The Core Invariant
Both sums are denominated in USD using live oracle prices at the moment of computation. The comparison is performed in WAD-precision fixed-point arithmetic - all values scaled to1e18 - so the on-chain check is:
If debt is zero, the account is unconditionally solvent - the check returns true and no division occurs.
Collateral Valuation
The Risk Engine recognizes two classes of collateral and values them differently. Direct collateral - XLM, USDC Balances are read from the Margin Account’s on-chain storage and multiplied by their oracle price. One oracle call per unique symbol, cached for the duration of the transaction. Blend yield positions - BLEND_XLM, BLEND_USDC When borrowed capital is deployed into Blend lending pools, the Margin Account receives b-tokens tracked by Vanna’s Tracking Token contract. These are not priced directly - they are first converted to their underlying asset amount via Blend’sb_rate:
The resulting underlying amount is then priced via the oracle at the underlying asset’s USD price. A Blend USDC position and a direct USDC deposit are treated identically for collateral purposes after this conversion.
For the full detail of how oracle prices enter the protocol and how the price cache works, see Oracle System.
Debt Valuation
Debt is read from each Lending Pool as raw borrow shares, not as the fully accrued token amount. Borrow shares represent the account’s proportional claim on a pool’s total outstanding borrows. Converting shares to the actual token amount owed - inclusive of all accrued interest - requires querying the pool’s current index, which in turn requires a call chain across Registry, RateModel, and LendingPool contracts. On Soroban, this chain exceeds the per-transaction computation budget for accounts with borrows across multiple pools. The consequence: the debt value used in a health check reflects the principal plus interest settled as of the last pool interaction, but excludes interest that has accrued since then. This creates a small understatement of true debt in the window between pool operations. This is a deliberate trade-off. The 1.1× threshold provides enough buffer that interest-accrual gaps between settlements do not compromise solvency before the next pool operation normalizes them. When any operation touches a pool - a borrow, a repay, a deposit, a withdrawal - interest is fully settled into shares, and the next health check reflects the true outstanding balance.The Three Guard Functions
The Risk Engine exposes three distinct health-check entry points. Each uses a different formula suited to the operation it gates.Borrow Guard
where = current collateral value, = current debt value, = USD value of the requested borrow amount. The borrow amount appears on both sides. This is the self-collateralization principle: capital borrowed from a Lending Pool cannot leave the Margin Account - it is immediately available as deployed collateral in the same account. The protocol therefore treats the incoming borrow as simultaneously increasing both the asset base and the debt, rather than only the debt. This is asymmetric with how standard overcollateralized lending protocols handle borrows, where borrowed capital leaves the account and the formula is .Withdraw Guard
where = USD value of the requested withdrawal. Standard collateral subtraction. The self-collateralization rationale does not apply - a withdrawal removes value from the account permanently. If the account carries no debt,has_debt() returns false and this check is skipped entirely.
Liquidation Guard
Liquidation is permitted whenis_account_healthy() returns false - i.e., the standard collateral-to-debt ratio has fallen below the threshold. The same function used for ongoing health assessment is the condition for liquidation eligibility, evaluated with the inverse outcome.
Maximum Leverage
The borrow guard’s formula directly determines the maximum leverage achievable from a clean account (zero existing debt, ): An account with no outstanding debt can borrow up to 10× its deposited collateral value before the borrow guard blocks. With existing debt (), the remaining borrow capacity is lower - the formula must be evaluated with the current debt balance to find the remaining room.The 1.1× Threshold
A threshold of 1.0× would render an account liquidatable precisely when collateral equals debt - leaving zero surplus. A liquidation executed at zero surplus faces three cost sources with no cover:- Slippage - selling collateral on-chain to repay debt incurs market impact. The larger the position, the higher the slippage relative to the mid-price.
- Oracle lag - prices update on Reflector’s cadence (approximately every 5 minutes). The on-chain price at liquidation time may lag the true market price by one or more ledger intervals.
total_assets decreases, reducing the vToken exchange rate and distributing the shortfall proportionally across LP positions. See vTokens for the exchange rate mechanics.
Related
- Liquidation - what happens when an account falls below 1.1×
- Oracle System - how prices enter the protocol and the price cache works
- Lending Pools - where borrow shares are stored and interest accrues
- Margin Accounts - the isolated contract whose state the Risk Engine reads
- vTokens - how LP positions absorb bad debt via exchange rate dilution
- Interest Rate Model - the rate that determines how fast debt grows toward the threshold

