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

# Router contract

> The on-chain entrypoint that executes every aggregator swap.

Every transaction the API produces calls the same canonical router contract on Base.

<Card title="O1Router on Base" icon="cube">
  * **Address:** [`0x8Dc736C6BA12e1Df1c73DB6BED8d7573F0aD90B3`](https://basescan.org/address/0x8Dc736C6BA12e1Df1c73DB6BED8d7573F0aD90B3)
  * **Chain ID:** `8453`
  * **Source:** [`contracts/src/O1Router.sol`](https://github.com/o1exchange/o1-dex-agg/blob/main/contracts/src/O1Router.sol)
</Card>

<Note>
  This is the only address you should ever approve as a spender for swaps via this API. If a `/submit` response returns a different `to` address, **abort and report it**.
</Note>

## What it does

The `O1Router` is a thin orchestrator that:

1. Pulls `tokenIn` from the user (via `transferFrom` or, if a `permit` is supplied, via `permit + transferFrom` in the same tx).
2. Optionally wraps `msg.value` to WETH when `useNativeIn` is set.
3. Dispatches each route leg to the corresponding venue adapter (Uniswap V2/V3/V4, Aerodrome, Pancake, Curve, DODO, WooFi, Hydrex, etc.).
4. Aggregates outputs from all routes.
5. Optionally unwraps WETH to native ETH when `unwrapNativeOut` is set.
6. Sends final `tokenOut` to the user.
7. Reverts if `actualOutput < minAmountOut` (slippage check), per-leg or globally.

## Public function signature

```solidity theme={null} theme={null}
function swapExactIn(
    SwapParams calldata params
) external payable returns (uint256 amountOut);
```

Where `SwapParams` is constructed by the API; you don't need to encode it yourself. Just send `submit.data` as the `data` field of your transaction.

## Slippage and safety

The router enforces three layers of protection:

<CardGroup cols={3}>
  <Card title="Per-leg minOut" icon="circle-check">
    Each leg has its own `minOut` checked by the corresponding adapter.
  </Card>

  <Card title="Global minAmountOut" icon="shield-check">
    The aggregate output is checked against `routePlan.minAmountOut`. The whole tx reverts if it's lower.
  </Card>

  <Card title="Permit deadline" icon="clock">
    If a `permit` payload is supplied, the EIP-712 deadline is enforced before the swap proceeds.
  </Card>
</CardGroup>

## Native wrapping

The router uses a configured wrapped-native token address. On Base that's WETH at `0x4200000000000000000000000000000000000006`.

* `useNativeIn: true` → router calls `WETH.deposit{value: msg.value}()` before dispatching legs.
* `unwrapNativeOut: true` → router calls `WETH.withdraw(amount)` after legs settle, then forwards ETH to the user.

You don't need to interact with WETH directly.

## Verifying on-chain

Before integrating, verify the deployment:

```bash theme={null} theme={null}
# Check that the bytecode at the address is non-empty
cast code 0x8Dc736C6BA12e1Df1c73DB6BED8d7573F0aD90B3 --rpc-url https://mainnet.base.org
```

Or just open it on [Basescan](https://basescan.org/address/0x8Dc736C6BA12e1Df1c73DB6BED8d7573F0aD90B3) and confirm:

* Contract is verified.
* Source matches `contracts/src/O1Router.sol` in the public repo.
* Constructor args set `WETH`, the fee recipient, and the venue adapter allowlist.

<Warning>
  Do not derive the router address from the API response without sanity checking it against this hardcoded value. Production integrations should hardcode the address and treat any mismatch in `submit.to` as fatal.
</Warning>
