Deposit Flow
Deposit places the user into a 2×-leveraged LP position in one atomic call. The borrow is internal (LT holds the debt, not the user); the user only provides the volatile asset.
sequenceDiagram
participant User
participant LT
participant AMM as LEVAMM
participant Cryptoswap
User->>LT: deposit(assets, debt, min_shares, receiver)
LT->>AMM: transferFrom(amm, LT, debt) %% crvUSD allocation
LT->>Cryptoswap: add_liquidity([debt, assets], 0, receiver=amm)
Cryptoswap-->>AMM: LP tokens (receiver)
LT->>AMM: _deposit(lp_tokens, debt) %% updates invariant state
LT->>User: mint yb-LP shares
LT->>LT: distribute_borrower_fees() %% refuel hook
Why the borrowed leg matches the deposit value
The debt parameter targets L = 2 inside the AMM. At equilibrium, AMM collateral value is about 2 × debt in crvUSD-denominated units. An LT deposit creates that collateral by adding the user's volatile asset plus the borrowed stable leg into Cryptoswap, so the LT-call estimate is:
Example: if the asset has 18 decimals, assets = 1e18, and the oracle price is 100_000e18 crvUSD per asset, then debt_estimate = 100_000e18 crvUSD. The resulting Cryptoswap LP collateral is roughly the volatile leg plus the borrowed stable leg, so AMM debt is about half of collateral value.
The tradeoff: leverage amplifies Cryptoswap fee capture (you hold 2× the LP exposure of a flat deposit) but also amplifies any IL-related drawdown if markets move before arbitrageurs have rebalanced LEVAMM back to L=2. Continuous rebalancing via arb (see Compounding Leverage) is what keeps the amplification bounded.
Safety band
At L = 2, the AMM enforces a band on coll_vs_debt = p_o × y / d of roughly 6.25% to 53.125% around the target. A debt that would push post-deposit state outside this band reverts — including debt = 0 in almost all cases. The edge-cases table below shows the concrete failure modes. Use LT.preview_deposit(assets, debt) to check before sending the transaction.
What happens inside Cryptoswap (separate from LEVAMM)
When LT calls add_liquidity, Cryptoswap may internally rebalance its price_scale if the deposit moves the pool's target price. This is not the same as LEVAMM rebalancing:
- Cryptoswap
price_scalerebalance — internal to the pool, fee-funded. May consume rebalance reserve whenprice_scaleshifts. Can impact all Cryptoswap LPs (including LEVAMM as holder). - LEVAMM L=2 drift correction — happens later via arb trades through
VirtualPool. Not triggered by this deposit directly.
The two are decoupled. Your deposit interacts with the first; the second cleans up any oracle-vs-LEVAMM drift afterwards.
Contracts touched
LT.vy— entry; manages share accounting and bucket reallocation.AMM.vy(LEVAMM) — receives LP as collateral, updates debt and invariant state via_deposit.- Curve Cryptoswap —
add_liquiditywith LEVAMM as receiver. - The
AMMaddress holds the borrowing budget (allocated byFactory.set_allocator); crvUSD flows from the AMM to LT to Cryptoswap.
Events emitted
LT.Deposit(sender, owner, assets, shares)AMM.AddLiquidityRaw(token_amounts, invariant, price_oracle)Cryptoswap.AddLiquidity(from the pool)LT.DistributeBorrowerFees(sender, amount, min_amount, discount)— on the refuel hook
Edge cases
| Case | Behaviour |
|---|---|
receiver == LT.staker() | Reverts "Deposit to staker" |
Post-deposit value > AMM.max_debt() / 2 | Reverts "Debt too high" |
Computed shares < min_shares | Reverts "Slippage" |
Post-mint shares + supply < MIN_SHARE_REMAINDER (1e6) | Reverts "Remainder too small" |
| Cryptoswap balance too imbalanced for the requested deposit | Reverts from Cryptoswap |
Gas
~ 300–500k on mainnet, dominated by add_liquidity and LEVAMM invariant solve.
Computing debt before the call
p_o = PriceOracle(oracle).price()
debt_estimate = assets * p_o // 10**asset_decimals
# Preview to check safety bounds before committing
shares_estimate = lt.preview_deposit(assets, debt_estimate)
preview_deposit reverts with "Debt too high" if debt_estimate would breach AMM.max_debt() / 2. To get a soft quote (return 0 instead of reverting), pass a third argument raise_overflow=False. LTMigrator and HybridVault use this path.