In a Sauce program, swap withStableSwap AMM optimized for low-slippage swaps between pegged assets (stablecoins, wrapped tokens). Uses a specialized invariant that provides near-zero slippage for like-kind assets while maintaining AMM properties.@sauce/router’s function for the venue (uniswapV2,uniswapV3,uniswapV4,curve,balancerV2, …; Slipstream, PancakeSwap V3 and Algebra pools throughuniswapV3), with a minimum output and, where the pool takes one, a price limit (the@sauce/routerreference; several pools under one limit, the distributed swap).
What it offers
- swap: Exchange tokens within a pool using index-based routing
- addLiquidity: Add liquidity with flexible token amounts (can be imbalanced)
- removeLiquidity: Remove liquidity proportionally or single-sided
Notes
- Pool tokens are indexed (i, j) not addressed; you must know the token order for each pool
- Common pool token orders: 3pool = [DAI(0), USDC(1), USDT(2)]
exchange_underlyingis used for metapools or lending pools where tokens wrap underlying assetsremove_liquidity_one_coinis useful for single-sided withdrawal (higher slippage than proportional)- Each pool is a separate contract; use the AddressProvider or registry to discover pools
- RouterNG enables cross-pool routing for multi-hop swaps across different pools
- The
get_virtual_pricenever decreases and represents the LP token value growth over time - Tokens must be ERC20-approved to the pool contract (not a router) for direct pool swaps
- For Router NG swaps, approve tokens to the Router NG contract
- The StableSwap-NG pool interface (plain and meta pools). Classic pools such as 3pool have their own shape: see
CurveThreePoolABIbelow. - 3pool (
threePoolin the addresses), a classic StableSwap pool. Its liquidity arrays are fixed-size, and its state-changing functions return nothing: read amounts as balance changes. - From a Pot program,
@sauce/routerswaps at the pool directly:curve(pool, tokenIn, tokenOut, amountIn, i, j, uint256Indices, minOut, recipient), withuint256Indicesfalsefor StableSwap and NG pools (int128indices) andtruefor CryptoSwap, approves the pool for exactlyamountInand calls the 4-argumentexchangewithminOutasmin_dy, without decoding a return (3pool-era pools have none); the allowance ends at zero, and it returns the Pot’s balance change, forwarded when the recipient is not the Pot.tryCurvecatches a failedexchange, resets the approval and returns0. ThecurveSwapaction is the same call. The Sauce Router’s own Curve handler cannot trade a pool whoseexchangereturns nothing, nor a uint256-index pool
Its names in a program
On Ethereum,Curve is a namespace: its contracts need no import.
Deployments
ABI
CurveAddressProviderABI
import CurveAddressProviderABI from "./protocols/curve/CurveAddressProviderABI.json"; Speaks for: addressProvider.
get_registry() view returns (address)get_address(uint256 _id) view returns (address)
CurveRouterNGABI
import CurveRouterNGABI from "./protocols/curve/CurveRouterNGABI.json"; Speaks for: routerNG.
exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _expected, address[5] _pools) payable returns (uint256)exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _min_dy, address[5] _pools, address _receiver) payable returns (uint256)get_dy(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, address[5] _pools) view returns (uint256)
CurveStableSwapABI
import CurveStableSwapABI from "./protocols/curve/CurveStableSwapABI.json";
exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) returns (uint256)exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) returns (uint256)add_liquidity(uint256[] amounts, uint256 min_mint_amount) returns (uint256)remove_liquidity(uint256 _amount, uint256[] min_amounts) returns (uint256[])remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) returns (uint256)get_dy(int128 i, int128 j, uint256 dx) view returns (uint256)get_virtual_price() view returns (uint256)
CurveThreePoolABI
import CurveThreePoolABI from "./protocols/curve/CurveThreePoolABI.json"; Speaks for: threePool.
exchange(int128 i, int128 j, uint256 dx, uint256 min_dy)add_liquidity(uint256[3] amounts, uint256 min_mint_amount)remove_liquidity(uint256 _amount, uint256[3] min_amounts)remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount)get_dy(int128 i, int128 j, uint256 dx) view returns (uint256)get_virtual_price() view returns (uint256)
Next steps
- Protocols: the other protocols, by what they do.
- Protocols and tokens: calling a contract by its namespace, or through its ABI.
- Glossary: the words these pages use, in plain terms.
