Uniswap V3 Swapping Functions Explained
Uniswap V3 is the most advanced AMM (Automated Market Maker) on Ethereum, providing efficient on-chain swapping for ERC20 tokens. When working with Uniswap from a smart contract, you interact with the router interface—specifically, ISwapRouter
—to perform swaps programmatically.
This blog will break down each major swap function (and their parameters!), so you can choose the right tool for your scenario and build powerful DeFi integrations.
The Four Core Uniswap V3 Swapping Methods
Uniswap V3's ISwapRouter
exposes four primary ways to swap tokens:
- exactInputSingle
- exactInput
- exactOutputSingle
- exactOutput
Let’s explain each in detail.
1. exactInputSingle
: Single Pool, Exact Input Amount
Purpose:
Swap a known amount of tokenIn
for as much tokenOut
as possible, all via a single Uniswap V3 pool.
Signature:
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
Parameters (packed in a struct):
-
tokenIn
: Address of input token (e.g., DAI). -
tokenOut
: Address of output token (e.g., WETH). -
fee
: Pool fee (500, 3000, or 10000 for 0.05%, 0.3%, 1%). -
recipient
: Where to send the output tokens. -
amountIn
: The fixed amount oftokenIn
to swap. -
amountOutMinimum
: Minimum amount oftokenOut
you will accept (prevents frontrunning/slippage). -
sqrtPriceLimitX96
: Optional. Sets a price boundary for the swap (0 for no limit).
Usage in Practice:
Simple swaps (DAI↔WETH, USDC↔USDT, etc.) without routing through multiple pairs.
Example scenario: Swap exactly 1000 DAI to receive the maximum possible amount of WETH.
2. exactInput
: Multi-hop, Exact Input Amount
Purpose:
Swap a known amount of tokenIn
for as much as possible of a final tokenOut
, possibly routing through several pools (multi-hop swap).
Signature:
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
Parameters (in a struct):
-
path
: Bytes data encoding token and fee sequence, e.g.,tokenA, feeAB, tokenB, feeBC, tokenC
. -
recipient
: Who receives the output tokens. -
amountIn
: The fixed amount oftokenIn
for the whole route. -
amountOutMinimum
: Minimum acceptable output.
Path Example (DAI → WETH → WBTC):
abi.encodePacked(DAI, uint24(3000), WETH, uint24(3000), WBTC)
Usage in Practice:
For swaps not directly supported in a single pool (e.g., DAI→WETH→WBTC), or to find the best route through intermediary assets.
3. exactOutputSingle
: Single Pool, Exact Output Amount
Purpose:
Receive an exact amount of tokenOut
while spending as little as possible of tokenIn
, via a single Uniswap pool.
Signature:
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
Parameters:
-
tokenIn
: Address of input token. -
tokenOut
: Address of output token. -
fee
: Pool fee. -
recipient
: Recipient of the output tokens. -
amountOut
: The desired, exact output amount oftokenOut
. -
amountInMaximum
: The most input tokens you’ll allow to be spent (slippage protection). -
sqrtPriceLimitX96
: Optional price boundary (set to 0 for no limit).
Usage in Practice:
You need exactly e.g. 1 ETH, but want to spend the minimum DAI possible, and you're willing to cap total input due to price impact or slippage.
4. exactOutput
: Multi-hop, Exact Output Amount
Purpose:
Receive an exact amount of tokenOut
via multiple pools, spending as little input as needed (but no more than your set maximum).
Signature:
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
Parameters:
-
path
: Bytes encoding the swap route from output to input (i.e., reversed compared toexactInput
!). -
recipient
: Who gets the output. -
amountOut
: The precise amount of output tokens you want. -
amountInMaximum
: The maximum input tokens you’re willing to spend.
Example path for WBTC (output) ← WETH ← DAI (input):
abi.encodePacked(WBTC, uint24(3000), WETH, uint24(3000), DAI)
(Note: Multi-hop exactOutput paths are reversed!)
Usage in Practice:
Useful for use-cases where you need to guarantee a specific payment amount in the output token (e.g., for NFT or fixed-price purchases), optimizing how little input you spend.
Struct Table
Function | Parameter Struct Name | Path Format | Guarantees |
---|---|---|---|
exactInputSingle | ExactInputSingleParams | N/A | Exact input |
exactInput | ExactInputParams | [tokenIn, fee, tokenMid, ...] | Exact input |
exactOutputSingle | ExactOutputSingleParams | N/A | Exact output |
exactOutput | ExactOutputParams | [tokenOut, fee, tokenMid, ...] reverse! | Exact output |
Key Design Patterns and Safety
- Always fill in
amountOutMinimum
/amountInMaximum
to guard against front-running and sandwich attacks. - Approve the router contract for any tokens you supply (
IERC20(tokenIn).approve(...)
). -
sqrtPriceLimitX96
is almost always safe at 0 unless you want to enforce a strict price boundary. - For multi-hop routes, ensure each pool (each hop) has liquidity!
Conclusion
Uniswap V3's router gives you immense flexibility :
- Use
exactInputSingle
for simple, one-hop max-output swaps. - Use
exactInput
for complex swaps through several pools with a fixed input. - Use
exactOutputSingle
andexactOutput
when you know exactly what you want to receive and want to cap your spending.
With this understanding, you can integrate efficient, robust DeFi swaps into your own contracts and dApps!
Further Reading:
Happy swapping!