Skip to main content
The RiskEngine is a stateless contract — it stores no user positions. On every call it reads position data from the caller’s SmartAccount and LendingPools, prices everything via Oracle, and returns a boolean. It never modifies state in those contracts; it only reads. Testnet address: CBL7RCG5H4VIZCNF7BRM2FQFXK7N5KRQKW7ZVEQZJKNXHA6FEU4OXK5I

Guard Functions

These are the three functions that gate every state-changing operation in the protocol. AccountManager calls the appropriate guard before every borrow, withdrawal, or liquidation.

is_borrow_allowed

Returns true if borrowing borrow_amt of symbol from the pool would leave the account healthy. Uses the gross-asset model — new borrows count as both an asset (purchased) and a liability simultaneously. Gross-asset borrow check:
Why gross-asset: If you borrow XLM and immediately deposit it into a Blend pool, your collateral increases by the same amount you borrowed. Without gross-asset accounting, this would look like infinite leverage.

is_withdraw_allowed

Returns true if withdrawing withdraw_amt of symbol collateral would leave the account healthy. Withdraw check:

is_account_healthy

Low-level comparator. Returns true if:
Where BALANCE_TO_BORROW_THRESHOLD = 1.1 × 10¹⁸. Used internally by is_borrow_allowed, is_withdraw_allowed, and by liquidation callers to check if an account is eligible for liquidation.

Portfolio Query Functions

get_current_total_balance

Returns the sum of all collateral held by margin_account, in USD WAD. Iterates every token in SmartAccount.get_all_collateral_tokens() and prices each one. Collateral valuation by type:

get_current_total_borrows

Returns the sum of all outstanding debt held by margin_account, in USD WAD. Queries each LendingPool’s get_borrow_balance() for each symbol in BorrowedTokensList.

Blend b-Token Valuation

When SmartAccount holds Blend b-tokens (received by depositing into Blend pool), the RiskEngine values them using the Blend pool’s b_rate:
b_rate is read directly from Blend’s pool reserve data. It represents the exchange rate from b-tokens to the underlying asset.

Symbol Canonicalization

Before querying Oracle prices, the RiskEngine maps wrapped token symbols to their underlying asset for pricing: LP tracking tokens (AQ_XLM_USDC, SS_XLM_USDC, AQ_XLM_AQUA, AQ_XLM_USDT) have no oracle feed and are valued at $0.

Price Caching

Within a single is_borrow_allowed or get_current_total_balance call, oracle prices are fetched once per symbol and cached in a local Map<Symbol, u128>. This avoids duplicate cross-contract oracle calls when the same symbol appears multiple times (e.g., both as collateral and debt).

Dust Threshold

Debts below 10^16 WAD (0.01 token in 18-decimal terms) are ignored during health checks. This prevents rounding-dust positions from blocking otherwise-healthy accounts.

Constants


Error Codes


Cross-Contract Reads

The RiskEngine reads from, but never writes to, other contracts: