Leverage Mechanics

This document explains how leverage and position sizing work across the Lava SDK so you can build correctly against the API and handle edge cases.

Key Takeaways

  1. maxLeverage and openLtv are lender-set parameters returned by the API. maxLeverage is the theoretical ceiling derived from openLtv. The API applies no buffers or caps beyond this.
  2. Leverage is exact for LONG. 5x means 5x your collateral goes to the swap. Fee is paid separately from the user's wallet and does not reduce the position.
  3. Leverage is approximate for SHORT. The fee is deducted from borrowed tokens before the swap, slightly reducing the effective position size.
  4. The on-chain LTV check is the only constraint. Near max leverage, swap slippage can push the position over the LTV limit and cause a revert. At lower leverage levels, this is not a concern.
  5. Capping user-facing leverage is your design decision. We provide a safe max formula as a reference, but the API gives you the raw values to implement your own approach.
  6. Use the /quote endpoint to preview expected swap output before calling /open.

What the API Returns

Offer fields

When you call GET /api/v1/offers/match, the matched offer includes these leverage-related fields:

FieldTypeDescription
maxLeveragestring (numeric)Maximum leverage this offer supports. Pre-computed from openLtv.
openLtvintegerThe lender's loan-to-value parameter in basis points (0-10000). This is the on-chain constraint that determines max leverage.

Relationship between the two:

maxLeverage = 10000 / (10000 - openLtv)
openLtv (bps)maxLeverage
50002.0x
75004.0x
900010.0x
920012.5x
950020.0x

Both values describe the same constraint. maxLeverage is the human-readable form; openLtv is what the on-chain program actually checks.

Quote response fields

When you call POST /api/v1/positions/quote, the response previews the Jupiter swap:

FieldTypeDescription
inAmountstringTotal swap input in smallest units. For LONG: the full positionSize. For SHORT: borrowAmount - fee.
outAmountstringExpected swap output (base tokens for LONG, USDC for SHORT)
otherAmountThresholdstringMinimum acceptable output after slippage
priceImpactPctstringJupiter-estimated price impact
inputMintstringToken being swapped from
outputMintstringToken being swapped to
slippageBpsintegerSlippage tolerance applied to the quote

For SHORT positions, the response also includes borrowAmount and fee.

Note: For LONG positions, the quote response currently does not include borrowAmount, fee, or positionSize as separate fields. You can derive them: positionSize = collateralAmount x leverage, borrowAmount = collateralAmount x (leverage - 1).


How Leverage Translates to Position Size

When you call POST /api/v1/positions/open with a leverage value, the API computes:

LONG:

positionSize = collateralAmount x leverage        (total swap input, in quote token units)
borrowAmount = collateralAmount x (leverage - 1)  (what the pool lends)

SHORT:

borrowAmount = collateralAmount x (leverage - 1)  (borrowed volatile tokens)
swapAmount   = borrowAmount - fee                 (what goes to the Jupiter swap)

The leverage parameter is your instruction to the protocol. At any leverage within the offer's range, you get exactly what you request (for LONG) or approximately what you request (for SHORT, due to fee deduction — see below).

Example: 5x LONG, 1 SOL collateral

FieldValue
collateralAmount1,000,000,000 lamports (1 SOL)
positionSize (swap input)5,000,000,000 lamports (5 SOL)
borrowAmount (from pool)4,000,000,000 lamports (4 SOL)
fee (feeBps of positionSize)Depends on partner config (see Revenue & Fees)
User wallet debitcollateral + fee
Jupiter swap5 SOL of quote token swapped to base token

The full 5 SOL goes to Jupiter. The fee does not reduce the swap amount for LONG.


How Fees Affect Leverage

For full details on fee structure, rates, and partner revenue sharing, see Revenue & Fees.

What matters for leverage mechanics is where the fee comes from — this differs between LONG and SHORT and directly affects position sizing.

LONG: Fee is paid separately from the user's wallet, on top of collateral. The full positionSize goes to the Jupiter swap. Leverage is exact.

SHORT: Fee is deducted from the borrowed tokens before the swap. The actual swap input is borrowAmount - fee, which slightly reduces the effective position size.

LONGSHORT
Fee deducted fromUser's wallet (separate)Borrowed tokens (before swap)
Reduces swap amount?NoYes
Leverage accuracyExactSlightly reduced by feeBps

On-Chain LTV Check

After the Jupiter swap executes, the on-chain program validates the position's health:

collateral_value x openLtv >= borrow_value x 10000

Where:

  • collateral_value = swap output tokens x oracle price (what you received from Jupiter)
  • borrow_value = borrowed amount x quote oracle price

This is the only on-chain constraint on leverage. The maxLeverage field is just the mathematical ceiling of this check. There are no additional buffers, fees, or caps applied server-side.

Why transactions can fail near max leverage

At low leverage (2-5x), the LTV is well below the openLtv limit. Swap slippage has no meaningful effect. Transactions succeed reliably.

Near max leverage, the LTV approaches the openLtv ceiling. Any swap slippage reduces collateral_value, pushing the actual LTV above the limit. The on-chain check fails and the transaction reverts with ExpectedCollateralNotEnough.

At leverage well below the max, the transaction will succeed regardless of normal slippage. For example, at 5x on a 12.5x offer, there is ~60% LTV headroom — slippage would need to be catastrophic to cause a failure.


Reference Implementation: Safe Maximum Leverage

The API returns the offer's theoretical maxLeverage. Whether and how you cap it for your users is your design decision. Below is how we handle it on lavarage.xyz — you can use this as a reference or implement your own approach.

The problem

At exactly maxLeverage, even 1 bps of swap slippage will cause the on-chain LTV check to fail. You need some headroom.

Safe max formula

Account for your slippage tolerance when computing a user-facing cap:

safeMaxLeverage = 1 / (1 - openLtv / 10000 x (1 - slippageBps / 10000))
openLtvOffer maxLeverageSafe Max (50 bps slippage)Safe Max (100 bps slippage)
900010.0x~9.5x~9.1x
920012.5x~11.8x~11.2x
950020.0x~18.1x~16.5x

Our frontend approach

On lavarage.xyz, we apply the safe max formula using the user's configured slippage tolerance (default: 50 bps). The slider and MAX button cap at this safe value. Users see the reduced max but can see the offer's raw maxLeverage in the token list.

Alternative approaches you might consider:

  • Show the raw maxLeverage and let the transaction fail, then suggest reducing leverage in the error handler
  • Apply a fixed buffer (e.g., 95% of maxLeverage)
  • Use the /quote endpoint's priceImpactPct to dynamically estimate safe headroom

Retry strategy

If a transaction fails with ExpectedCollateralNotEnough:

  1. Retry with slightly lower leverage (e.g., reduce by 0.5x)
  2. Or retry with higher slippageBps (e.g., increase from 50 to 100)
  3. Do not retry more than 2-3 times — persistent failures suggest the token is too volatile for that leverage level

Using the Quote Endpoint

Call POST /api/v1/positions/quote before opening to preview the swap. This lets you show users expected position size, entry price, and fees before they confirm.

Request:

{
  "offerPublicKey": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "userPublicKey": "GsbwXfJraMomNxBcjK7xK2xQx5MQgQx4Ld8QkLeNmA3v",
  "collateralAmount": "1000000000",
  "leverage": 5,
  "slippageBps": 50,
  "side": "LONG"
}

Response:

{
  "inAmount": "5000000000",
  "outAmount": "33250000",
  "priceImpactPct": "0.01",
  "otherAmountThreshold": "33083750",
  "inputMint": "So11111111111111111111111111111111111111112",
  "outputMint": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
  "slippageBps": 50
}

How to compute entry price from the quote:

entryPrice = inAmount / outAmount (adjusted for token decimals)

Error Handling

Error CodeCauseRecommended Action
LEVERAGE_UNAVAILABLERequested leverage exceeds offer's maxLeverageReduce leverage or use /offers/match to find a higher-leverage offer
ExpectedCollateralNotEnough (on-chain)Swap slippage pushed LTV above openLtvRetry with lower leverage or higher slippageBps (see retry strategy above)
POSITION_TOO_SMALLProtocol fee exceeds borrow amountIncrease collateralAmount or leverage
SWAP_QUOTE_FAILEDJupiter could not route the swapToken may be illiquid; try a different pair or smaller size