Skip to content

Swap

Exchange one token for another at the pool’s current price. Swap is a mutating dispatch primitive — it routes to the protocol-specific exact-input swap underneath the unified interface. See The Primitive Contract for the cross-cutting invariants every dispatcher follows.

V2/V3 are binary pools (exactly two assets), so the output token is implicit — only token_in is named. Balancer and Stableswap are N-asset pools (N ≥ 2), so both token_in and token_out must be named explicitly.

ProtocolRequired call shape
Uniswap V2Swap().apply(lp, token_in, user_nm, amount_in)
Uniswap V3Swap().apply(lp, token_in, user_nm, amount_in, sqrt_price_limit=None)
BalancerSwap().apply(lp, token_in, token_out, user_nm, amount)
StableswapSwap().apply(lp, token_in, token_out, user_nm, amount)
ParameterTypeDescription
lpExchangeInitialized pool object. Must already have liquidity (post-Join).
token_inERC20Token the user is handing over. Direction of the trade is determined by which token is named here.
user_nmstrAccount name debited for token_in and credited for the output token.

The trailing parameters and the input-amount conventions diverge per protocol — see below.

Exact-input swap on a constant-product pool. The output token is the other token in the pair (binary pool, so it’s implicit). Returns the integer-floored output amount.

ParameterTypeNotes
amount_infloatAmount of token_in swapped into the pool. The output amount is computed via lp.get_amount_out(...) and floored to an integer in V2.
from defipy import Swap
# Swap 1000 DAI for ETH
out = Swap().apply(lp, dai, "user", 1000)
# `out` is the floored amount of ETH received

Exact-input swap inside the pool’s active range. Direction is inferred from whether token_in matches token0 or token1swapExact0For1 or swapExact1For0 is invoked accordingly. The optional sqrt_price_limit is the V3 slippage-protection parameter (passing None disables it).

ParameterTypeNotes
amount_infloatAmount of token_in to swap.
sqrt_price_limitint (optional)Lower (or upper) bound on the post-swap sqrt-price, in V3’s Q64.96 fixed-point format. None means no limit.
from defipy import Swap
# Same call shape as V2 — V3 is figured out from lp.version
Swap().apply(lp, tkn, "user", 1000)
# To enforce a sqrt-price limit, pass it as the fifth positional arg.

Exact-input or exact-output swap on an N-asset weighted pool. Because Balancer pools may hold more than two tokens, both token_in and token_out must be named — the pool can’t infer direction. The kind constructor parameter selects the swap mode:

  • Proc.SWAPOUT (default) — exact-input. amount is token_in quantity entering the pool.
  • Proc.SWAPIN — exact-output. amount is token_out quantity leaving the pool.
ParameterTypeNotes
token_outERC20Token the user receives. Required because the pool has N ≥ 2 assets.
amountfloatQuantity of token_in (SWAPOUT) or token_out (SWAPIN), per the constructor mode.
from defipy import Swap
from balancerpy.enums import Proc
# Exact-input: swap exactly 10 DAI for whatever USDC comes out
Swap().apply(lp, dai, usdc, "user", 10)
# Exact-output: receive exactly 0.5 ETH; pay whatever DAI is required
Swap(kind=Proc.SWAPIN).apply(lp, dai, eth, "user", 0.5)

Exact-input swap on a Stableswap pool with amplification coefficient A. Like Balancer, both tokens must be named. There is no SWAPIN mode on Stableswap — only exact-input is exposed.

ParameterTypeNotes
token_outERC20Token the user receives.
amountfloatAmount of token_in entering the pool.
from defipy import Swap
# Stableswap is exact-input only; trades close to peg behave near-linearly,
# trades far from peg encounter the depeg basin.
Swap().apply(lp, dai, usdc, "user", 10)

For analyzing depeg risk before swapping, see AssessDepegRisk — it quantifies exposure as the trade pushes the pool away from the peg.

How Swap interacts with the rest of the pipeline

Section titled “How Swap interacts with the rest of the pipeline”
  1. Join — initialize the pool.
  2. Swap — exercise the pool with trades (this primitive). Each swap accrues fees and moves the spot price.
  3. Pre-trade analytics (Agentic Primitives) — CalculateSlippage for the price-impact and slippage of a proposed swap; DetectMEV for sandwich-risk exposure.
  4. Post-trade analyticsAnalyzePosition to decompose any LP’s resulting IL vs fee income.