> ## Documentation Index
> Fetch the complete documentation index at: https://docs.swaps.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Stableswap on EVM

> Integrate the GhostExchange contract directly — quoting, swapping, and pool discovery over cross-collateral stable liquidity.

On EVM, Swaps' stableswap protocol is integrated through the `GhostExchange`
contract — a single-chain swap interface built on paired
CrossCollateralRouter pools, with built-in quoting, slippage protection, and
deadline enforcement. It is designed to slot into a DEX aggregator's routing
graph as a standard quote-and-swap venue.

## Deployments

| Chain    | Address                                      |
| -------- | -------------------------------------------- |
| Ethereum | `0xfEAeB7cEFe9f7A42386130af4e1C70a2f0f92F8c` |
| Arbitrum | `0xb9AFF99b40B65C45ab0Fc99146225C05FEd95c3d` |
| Base     | `0x369c56802016d699AE7b06b82c0FB98461ff2eF6` |
| Polygon  | `0xbE824336888799052d7dc2Cd5Cf18e19d18D77D3` |
| Binance  | `0xeCE62f04A5573CE0e30228cD0fB56A8f8e84fcd0` |

<Info>
  Integration is permissionless at **default rates**. The `recipient`
  parameter on quotes is used for **fee lookup**: recipients with custom
  pricing configured by Swaps quote at their negotiated rates. [Reach out to
  us](https://console.swaps.xyz) to arrange custom pricing for your
  integration.
</Info>

## Discover available pairs

Index `PoolAdded` and `PoolRemoved` events to build the set of active pairs:

```solidity theme={null}
event PoolAdded(address indexed tokenA, address indexed tokenB);
event PoolRemoved(address indexed tokenA, address indexed tokenB);
```

To confirm a specific pair on-chain:

```solidity theme={null}
function pools(address tokenA, address tokenB) external view returns (address routerIn, address routerOut);
```

A non-zero return means the pair is tradeable. Pairs are bidirectional.

## Liquidity

The maximum output for a pair is bounded by the target router's token balance:

```solidity theme={null}
(, address routerOut) = ghostExchange.pools(tokenIn, tokenOut);
uint256 maxOutput = IERC20(tokenOut).balanceOf(routerOut);
```

## Quote

Both quote functions are `view` — no gas, no state changes.

```solidity theme={null}
function quoteExactInput(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    address recipient
) external view returns (uint256 amountOut);

function quoteExactOutput(
    address tokenIn,
    address tokenOut,
    uint256 amountOut,
    address recipient
) external view returns (uint256 amountIn);
```

## Swap

The caller must `approve` GhostExchange for `tokenIn` before calling.

```solidity theme={null}
function swapExactInput(
    address tokenIn,
    address tokenOut,
    address recipient,     // receives tokenOut
    uint256 amountIn,
    uint256 amountOutMin,  // slippage guard — reverts with TooLittleReceived
    uint256 deadline       // block.timestamp guard — reverts with DeadlineExpired
) external returns (uint256 amountOut);

function swapExactOutput(
    address tokenIn,
    address tokenOut,
    address recipient,     // receives tokenOut
    uint256 amountOut,
    uint256 amountInMax,   // slippage guard — reverts with TooMuchRequested
    uint256 deadline
) external returns (uint256 amountIn);
```

## Typical flow

**Exact input** — sell a known amount of `tokenIn`:

```text theme={null}
1. amountOut = GhostExchange.quoteExactInput(tokenIn, tokenOut, amountIn, recipient)
2. IERC20(tokenIn).approve(ghostExchange, amountIn)
3. GhostExchange.swapExactInput(tokenIn, tokenOut, recipient, amountIn, amountOutMin, deadline)
```

**Exact output** — buy a known amount of `tokenOut`:

```text theme={null}
1. amountIn = GhostExchange.quoteExactOutput(tokenIn, tokenOut, amountOut, recipient)
2. IERC20(tokenIn).approve(ghostExchange, amountIn)
3. GhostExchange.swapExactOutput(tokenIn, tokenOut, recipient, amountOut, amountInMax, deadline)
```

## Revert conditions

| Error               | Cause                                                    |
| ------------------- | -------------------------------------------------------- |
| `PoolDoesNotExist`  | No registered pair for tokenIn/tokenOut                  |
| `AmountTooSmall`    | Input too small to produce any output after fees/scaling |
| `TooLittleReceived` | Output \< `amountOutMin`                                 |
| `TooMuchRequested`  | Required input > `amountInMax`                           |
| `DeadlineExpired`   | `block.timestamp > deadline`                             |

## Related

* [Stableswap on Solana](/protocol-reference/stableswap-solana) — the same
  protocol as a native Solana program.
* [Stableswaps via the API](/guides/stableswaps) — the same liquidity through
  a single `getAction` call.
