Skip to main content
Every transaction the API produces calls the same canonical router contract on Base.

O1Router on Base

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.

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

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:

Per-leg minOut

Each leg has its own minOut checked by the corresponding adapter.

Global minAmountOut

The aggregate output is checked against routePlan.minAmountOut. The whole tx reverts if it’s lower.

Permit deadline

If a permit payload is supplied, the EIP-712 deadline is enforced before the swap proceeds.

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:
# 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 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.
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.