Skip to content

RemoveLiquidity

Withdraw underlying tokens by burning LP shares. RemoveLiquidity is a mutating dispatch primitive. The user-facing interface is uniform — specify a token and an amount — but what “amount” means differs by protocol.

ProtocolRequired call shape
Uniswap V2RemoveLiquidity().apply(lp, token, user_nm, amount)
Uniswap V3RemoveLiquidity().apply(lp, token, user_nm, amount, lwr_tick, upr_tick)
BalancerRemoveLiquidity(kind=Proc.REMOVETKN).apply(lp, token_out, user_nm, amount_out)
StableswapRemoveLiquidity().apply(lp, token_out, user_nm, amount_out)
ParameterTypeDescription
lpExchangeInitialized pool with active liquidity owned by user_nm.
tokenERC20The token side the user is anchoring the withdrawal against.
user_nmstrAccount name whose LP shares are burned.
amountfloatQuantity associated with token. The semantics differ by protocol — see the per-protocol sections below.

The user names a token side and the amount they want from that side. The dispatcher computes the LP-share burn from the pool’s reserves and total liquidity, then calls lp.remove_liquidity(...) and returns both tokens at the current pool ratio.

ParameterTypeNotes
amountfloatAmount of the named token to receive. The dispatcher computes liq = amount × tot_liq / res_token and the matching opposite-side amount via the pool ratio.
from defipy import RemoveLiquidity
# Burn enough LP to receive 5 ETH on the ETH side; receive matching DAI too
out = RemoveLiquidity().apply(lp, eth, "user", 5)
# out = {token0: amount0, token1: amount1} — both tokens

Same single-token-anchored shape as V2, plus the position’s tick range. The dispatcher computes the in-range liquidity to burn from amount and the active sqrt-price (liq = amount * sqrt_P or amount / sqrt_P depending on which side token is on), then calls lp.burn(user_nm, lwr_tick, upr_tick, liq).

ParameterTypeNotes
lwr_tickintLower tick of the position to withdraw from. Must match the range you originally minted into.
upr_tickintUpper tick.
from defipy import RemoveLiquidity
RemoveLiquidity().apply(lp, eth, "user", 5, lwr_tick, upr_tick)

You also receive both tokens at the current sqrt-price ratio for that range (returned as {token0: amount0, token1: amount1}).

Single-asset withdrawal is first-class. The constructor kind selects mode:

  • Proc.REMOVETKN (default) — pass amount_out, the token quantity you want; pool computes the LP-share burn via lp.exit_swap_extern_amount_out(...).
  • Proc.REMOVESHARES — pass an LP-share amount to burn; pool computes the resulting token-out via lp.exit_swap_pool_amount_in(...).
ParameterTypeNotes
token_outERC20The single asset you want to receive.
amount_outfloatToken-out quantity (REMOVETKN) or LP-shares to burn (REMOVESHARES).
from defipy import RemoveLiquidity
from balancerpy.enums import Proc
# Withdraw exactly 1 ETH worth out of an ETH/DAI/USDC pool
RemoveLiquidity().apply(lp, eth, "user", 1)
# Or burn a known share amount and let the pool compute the ETH-out
RemoveLiquidity(kind=Proc.REMOVESHARES).apply(lp, eth, "user", 5)

Single-asset withdrawal is also first-class on Stableswap. There is no kind parameter — only token-out-amount mode is exposed. The dispatcher calls lp.remove_liquidity(amount_out, token_out, user_nm).

ParameterTypeNotes
token_outERC20The single asset you want to receive.
amount_outfloatQuantity of token_out to receive.
from defipy import RemoveLiquidity
RemoveLiquidity().apply(lp, dai, "user", 1000)

Like Balancer, the pool absorbs the imbalance against the invariant — that’s why Stableswap doesn’t need a separate WithdrawSwap primitive (see the WithdrawSwap page for the architectural reason).

How RemoveLiquidity interacts with the rest of the pipeline

Section titled “How RemoveLiquidity interacts with the rest of the pipeline”
  1. JoinAddLiquidity — pool initialized and LPs deposited.
  2. Pre-withdrawal analyticsAnalyzePosition decomposes the LP’s IL vs accumulated fees so the user can decide whether now is the right time to exit.
  3. RemoveLiquidity — burn LP, take the proceeds (this primitive).
  4. Compare alternativesWithdrawSwap (V2/V3 only) for single-asset exits without an intermediate manual swap.