Skip to content

AddLiquidity

Contribute liquidity to a pool that already has a price. AddLiquidity is a mutating dispatch primitive — every protocol accepts a single-token-in call shape, but the meaning of “what’s calculated for you” varies. See The Primitive Contract for the cross-cutting invariants every dispatcher follows.

ProtocolRequired call shape
Uniswap V2AddLiquidity().apply(lp, token_in, user_nm, amount_in)
Uniswap V3AddLiquidity().apply(lp, token_in, user_nm, amount_in, lwr_tick, upr_tick)
BalancerAddLiquidity(kind=Proc.ADDTKN).apply(lp, token_in, user_nm, amount_in)
StableswapAddLiquidity().apply(lp, token_in, user_nm, amount_in)
ParameterTypeDescription
lpExchangeInitialized pool object. Must already have liquidity (post-Join).
token_inERC20The token being deposited. Determines which side of the pair (V2/V3) or which vault asset (Balancer/Stableswap) the user is funding.
user_nmstrAccount name credited with the resulting LP shares.
amount_infloatQuantity of token_in to deposit. The pool resolves what’s needed for the other side internally.

Single-token-in, two-sided deposit. The dispatcher calls lp.quote(amount_in, reserve_in, reserve_out) to compute the matching amount of the other token at the current price ratio, then both balances go into lp.add_liquidity(...). The user effectively pays both tokens, but only specifies one.

ParameterTypeNotes
(no extras)Just the common parameters above.
from defipy import AddLiquidity
# Add 10 ETH-worth — the matching DAI amount is computed from current reserves
AddLiquidity().apply(lp, eth, "user", 10)

The user must already hold the matching amount of the other token; the dispatcher does not swap to obtain it. If you want swap-and-deposit in one shot, use SwapDeposit.

Returns {token0: balance0, token1: balance1}.

Single-token-in deposit into a specific tick range. The dispatcher computes the in-range liquidity L from amount_in and the active sqrt-price (UniV3Helper.calc_Lx or calc_Ly depending on which side token_in is), then calls lp.mint(user_nm, lwr_tick, upr_tick, L).

ParameterTypeNotes
lwr_tickintLower tick of the range. Must be tick_spacing-aligned.
upr_tickintUpper tick. Must be > lwr_tick and tick_spacing-aligned.
from defipy import AddLiquidity, UniV3Utils
tick_spacing = 60
lwr_tick = UniV3Utils.getMinTick(tick_spacing)
upr_tick = UniV3Utils.getMaxTick(tick_spacing)
AddLiquidity().apply(lp, eth, "user", 10, lwr_tick, upr_tick)

Single-asset deposit against a vault. The constructor kind parameter selects the deposit mode:

  • Proc.ADDTKN (default) — pass a token amount; pool computes the LP shares to mint via lp.join_swap_extern_amount_in(amount_in, token_in, user_nm).
  • Proc.ADDSHARES — pass desired LP shares; pool computes the required token amount via lp.join_swap_pool_amount_out(amount_in, token_in, user_nm). The third positional arg is now the share amount you want to receive.
ParameterTypeNotes
(no extras)The constructor kind selects mode; apply() itself takes the common parameters only.
from defipy import AddLiquidity
from balancerpy.enums import Proc
# Default: deposit 1 ETH; receive whatever shares the pool issues
AddLiquidity().apply(lp, eth, "user", 1)
# Inverted: receive exactly 5 shares; pay whatever ETH is required
AddLiquidity(kind=Proc.ADDSHARES).apply(lp, eth, "user", 5)

The pool internally handles the imbalance — that’s why Balancer doesn’t need a separate SwapDeposit primitive (see the SwapDeposit page for the architectural reason).

Single-asset deposit against a Stableswap vault. The dispatcher calls lp.add_liquidity(amount_in, token_in, user_nm). There is no kind parameter on Stableswap’s AddLiquidity constructor — token-amount-in is the only exposed mode.

ParameterTypeNotes
(no extras)Common parameters only.
from defipy import AddLiquidity
AddLiquidity().apply(lp, dai, "user", 1000)

Like Balancer, the pool absorbs the imbalance internally — single-asset adds are first-class on Stableswap.

How AddLiquidity interacts with the rest of the pipeline

Section titled “How AddLiquidity interacts with the rest of the pipeline”
  1. Join — pool must be initialized first.
  2. AddLiquidity — additional LPs contribute liquidity (this primitive).
  3. Pre-deposit analyticsOptimalDepositSplit (V2-only) projects the optimal split before depositing; EvaluateRebalance projects whether re-adding into a different range/composition is worth the cost.
  4. Post-deposit analyticsAnalyzePosition decomposes IL vs fees over time.