WAD Arithmetic
Constants
| Constant | Value | Meaning |
|---|---|---|
WAD | 10¹⁸ | Fixed-point 1.0 |
SCALAR_12 | 10¹² | Blend b_rate divisor |
SECS_PER_YEAR | 31,556,952 × 10¹⁸ | Seconds in a year in WAD |
Core Operations
mul_wad_down, div_wad_down). This means rounding errors accumulate against the protocol, not in the protocol’s favor.
Decimal Conversion
Every asset has native decimals (XLM: 7, USDC: 6). Balances are converted to WAD at protocol entry and back to native decimals at exit.Interest Rate Model
Utilization Ratio
liquidity_wad is the pool’s current asset balance in WAD.
Borrow Rate Per Second
Vanna uses a smooth polynomial curve (not a kinked two-slope model):| Coefficient | Value | Decimal |
|---|---|---|
c1 | 10^17 | 0.1 |
c2 | 3 × 10^17 | 0.3 |
c3 | 35 × 10^17 | 3.5 |
util^32 and util^64 terms are computed via WAD exponentiation (rpow_wad). At low utilization the curve is nearly linear. At high utilization the polynomial terms dominate, pushing rates up sharply.
Annual Rate Derivation
To get the annualized rate for display:Interest Accrual
Rate Factor
Computed at every borrow or repayment (update_state()):
State Update
now == last_updated the function exits early — no double-accrual within the same ledger.
Live (Preview) Borrows
When computing health factors, the protocol uses live borrows (including interest that has accrued since the last state update but not yet written to storage):Borrow Share Accounting
Borrows are tracked via shares, not raw amounts. This lets interest accrue globally without updating each user’s record.Issuing Shares (on Borrow)
Burning Shares (on Repay)
Computing User Debt
borrows_wad (stored, slightly stale), while share issuance uses borrows_live (fresh). This is intentional — it prevents over-issuance of shares.
Origination Fee
On every borrow, a one-time fee is charged:borrow_amount - origination_fee.
vToken Exchange Rate
vTokens represent a proportional share of a pool’s total assets (pool_balance + borrows_wad).
Minting on Deposit
Redeeming on Withdrawal
Exchange Rate
The implicit exchange rate grows as interest accrues:borrows_wad grows with interest, total_assets grows, and each vToken is worth more underlying.
Health Factor
The health factor is a ratio of total collateral value to total debt value.HF > 1.1 × WAD (strictly greater than)Liquidatable:
HF ≤ 1.1 × WAD
Collateral Valuation
Different collateral types are valued differently: Raw tokens (XLM, USDC):b_rate is fetched from the Blend pool’s reserve data.
LP tracking tokens (AQ_XLM_USDC, SS_XLM_USDC):
Borrow-Time Check (Gross-Asset Model)
When evaluating a new borrow, both the new borrow and existing borrows count as assets:HF > 1 instead of near zero.
Withdraw-Time Check
Liquidation Check
Uses pure collateral (not gross-asset model):Constants
| Constant | Value | Description |
|---|---|---|
BALANCE_TO_BORROW_THRESHOLD | 1.1 × 10¹⁸ | Minimum health factor (110%) |
dust_debt_threshold | 10^16 | Debts below this are ignored in health checks |
Oracle Price Conversion
Prices from the Reflector oracle come as(price: u128, decimals: u32). The RiskEngine converts to WAD:
Token Symbol Canonicalization
Before price lookup, the RiskEngine maps wrapped token symbols to their underlying asset:| Input symbol | Canonical symbol | Price feed |
|---|---|---|
BLUSDC, AQUSDC, SOUSDC | USDC | USDC/USD |
AQUARIUS_USDC, SOROSWAP_USDC | USDC | USDC/USD |
BLEND_XLM | XLM | XLM/USD |
BLEND_USDC | USDC | USDC/USD |
Soroswap/Aquarius AMM Formulas
Optimal Liquidity Amount (Add Liquidity)
Given pool reserves(R_a, R_b) and desired inputs (A_desired, B_desired):
Swap Output (Soroswap, 0.3% fee)
x × y = k):
Storage TTL
All persistent storage keys are extended with a TTL to prevent ledger entry expiry:| Key type | TTL |
|---|---|
| Contract data (short) | 6,307,200 ledgers (~1 year) |
| Contract data (long) | 63,072,000 ledgers (~10 years) |

