# Swap Router

#### Exact Input (Single Hop) <a href="#user-content-exact-input-single-hop" id="user-content-exact-input-single-hop"></a>

```
struct ExactInputSingleParams {    address tokenIn;    address tokenOut;    uint24 fee;    address recipient;    uint256 deadline;    uint256 amountIn;    uint256 amountOutMinimum;    uint160 sqrtPriceLimitX96;}function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)
```

Swaps an exact amount of input tokens for as many output tokens as possible in a single pool.

**Parameters:**

| Field               | Description                           |
| ------------------- | ------------------------------------- |
| `tokenIn`           | Token to swap from                    |
| `tokenOut`          | Token to swap to                      |
| `fee`               | Pool fee tier (100, 500, 3000, 10000) |
| `recipient`         | Address to receive output tokens      |
| `deadline`          | Transaction expiry timestamp          |
| `amountIn`          | Exact amount of input tokens          |
| `amountOutMinimum`  | Minimum output (slippage protection)  |
| `sqrtPriceLimitX96` | Price limit (0 = no limit)            |

**Example:**

```
// Swap exactly 1000 USDC for WETHISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({    tokenIn: USDC,    tokenOut: WETH,    fee: 3000,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountIn: 1000e6,    amountOutMinimum: 0.4e18,  // Min 0.4 WETH    sqrtPriceLimitX96: 0});uint256 amountOut = swapRouter.exactInputSingle(params);
```

***

#### Exact Input (Multi-Hop) <a href="#user-content-exact-input-multi-hop" id="user-content-exact-input-multi-hop"></a>

```
struct ExactInputParams {    bytes path;    address recipient;    uint256 deadline;    uint256 amountIn;    uint256 amountOutMinimum;}function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut)
```

Swaps an exact amount of input tokens through multiple pools for maximum output.

**Path Encoding:**

* Format: `abi.encodePacked(tokenA, feeAB, tokenB, feeBC, tokenC)`
* Example: USDC → (3000) → WETH → (3000) → DAI

**Example:**

```
// Swap USDC → WETH → DAIbytes memory path = abi.encodePacked(USDC,uint24(3000),  // 0.3% USDC/WETH poolWETH,uint24(3000),  // 0.3% WETH/DAI pool DAI);ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({    path: path,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountIn: 1000e6,    amountOutMinimum: 950e18});uint256 amountOut = swapRouter.exactInput(params);
```

***

#### Exact Output (Single Hop) <a href="#user-content-exact-output-single-hop" id="user-content-exact-output-single-hop"></a>

```
struct ExactOutputSingleParams {
    address tokenIn;    
    address tokenOut;    
    uint24 fee;    
    address recipient;    
    uint256 deadline;    
    uint256 amountOut;    
    uint256 amountInMaximum;    
    uint160 sqrtPriceLimitX96;
}

function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn)
```

Swaps as few input tokens as possible for an exact amount of output tokens.

**Example:**

```
// Receive exactly 1 WETH, spending at most 2500 USDCISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({    tokenIn: USDC,    tokenOut: WETH,    fee: 3000,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountOut: 1e18,       // Exactly 1 WETH    amountInMaximum: 2500e6,    sqrtPriceLimitX96: 0});uint256 amountIn = swapRouter.exactOutputSingle(params);// Refund excess: if (amountIn < 2500e6) refund the difference
```

***

#### Exact Output (Multi-Hop) <a href="#user-content-exact-output-multi-hop" id="user-content-exact-output-multi-hop"></a>

```
struct ExactOutputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountOut;
    uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn)
```

Swaps through multiple pools to receive an exact output amount.

**Path Encoding (Reversed):**

* Format: `abi.encodePacked(tokenC, feeBC, tokenB, feeAB, tokenA)`
* For USDC → WETH → DAI, encode as: DAI → WETH → USDC

**Example:**

```
// Get exactly 1000 DAI via USDC → WETH → DAIbytes memory path = abi.encodePacked(    DAI,           // Output token (reversed!)    uint24(3000),    WETH,    uint24(3000),    USDC           // Input token (reversed!));ISwapRouter.ExactOutputParams memory params = ISwapRouter.ExactOutputParams({    path: path,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountOut: 1000e18,    amountInMaximum: 1050e6});uint256 amountIn = swapRouter.exactOutput(params);
```

***

### Token Approvals <a href="#user-content-token-approvals" id="user-content-token-approvals"></a>

Before swapping, approve the router to spend your tokens:

```
IERC20(tokenIn).approve(address(swapRouter), amountIn);
```

***

### Handling Native ETH <a href="#user-content-handling-native-eth" id="user-content-handling-native-eth"></a>

For ETH swaps, use WETH as `tokenIn` or `tokenOut` and send ETH with the transaction:

```
// Swap ETH for USDC
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({tokenIn: WETH,tokenOut: USDC,fee: 3000,recipient: msg.sender,deadline: block.timestamp + 300,amountIn: 1e18,amountOutMinimum: 2000e6,sqrtPriceLimitX96: 0});swapRouter.exactInputSingle{value: 1e18}(params);
```

***

### Price Limits <a href="#user-content-price-limits" id="user-content-price-limits"></a>

Set `sqrtPriceLimitX96` to prevent execution beyond a certain price:

* **Zero for one** (token0 → token1): Price cannot go below this value
* **One for zero** (token1 → token0): Price cannot go above this value
* **Set to 0**: No price limit

***

### Best Practices <a href="#user-content-best-practices" id="user-content-best-practices"></a>

1. **Always set slippage protection**: Use `amountOutMinimum` / `amountInMaximum`
2. **Use deadlines**: Set reasonable expiry times (e.g., 5 minutes)
3. **Multi-hop carefully**: More hops = more gas + more slippage
4. **Check routes**: Use off-chain router to find optimal paths
5. **Handle refunds**: For exact output swaps, refund unused input tokens

***

### Interface <a href="#user-content-interface" id="user-content-interface"></a>

```
interface ISwapRouter {
    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); 
    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.warpx.exchange/for-developers/warpx-v3/periphery/swap-router.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
