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

# Native ETH

> Sell native ETH or receive native ETH directly, without manually wrapping or unwrapping WETH.

The `O1Router` handles all wrapping and unwrapping internally. From the API caller's perspective there are two flags:

| Flag              | Where                      | What it does                                                                                   |
| ----------------- | -------------------------- | ---------------------------------------------------------------------------------------------- |
| `useNativeIn`     | `/submit` (and `/execute`) | When `true`, send `msg.value = amountIn` and the router wraps to WETH before dispatching legs. |
| `unwrapNativeOut` | `/submit` (and `/execute`) | When `true`, the router unwraps WETH to ETH for the recipient before completing the swap.      |

## Sentinel addresses for native ETH

When you want to swap **native ETH** in `tokenIn` or `tokenOut`, use one of these sentinels:

| Sentinel                                     | Notes                                           |
| -------------------------------------------- | ----------------------------------------------- |
| `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` | Standard EIP-7528 native sentinel. Recommended. |
| `0x0000000000000000000000000000000000000000` | Zero-address fallback, also accepted.           |

The aggregator detects either form and sets `routePlan.nativeIn` or `routePlan.nativeOut` to `true` automatically. You still need to set the corresponding flag on `/submit` or `/execute`, since the user might have changed their mind about wrapping between quote and submit.

## The four common cases

<Tabs>
  <Tab title="ETH → ERC-20">
    Sell native ETH, receive an ERC-20 like USDC.

    **Quote:**

    ```json theme={null} theme={null}
    {
      "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      "tokenOut": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
      "amountIn": "1000000000000000000",
      "slippageBps": 100,
      "chainId": 8453
    }
    ```

    **Submit:**

    ```json theme={null} theme={null}
    {
      "quoteId": "...",
      "user": "0x...",
      "useNativeIn": true
    }
    ```

    **Send transaction:** the response `value` will equal `amountIn` (`1000000000000000000`).

    ```ts theme={null} theme={null}
    await walletClient.sendTransaction({
      to: submit.to,
      data: submit.data,
      value: BigInt(submit.value), // = 1 ETH
    });
    ```

    **Approval:** none needed.
  </Tab>

  <Tab title="ERC-20 → ETH">
    Sell an ERC-20 like USDC, receive native ETH.

    **Quote:**

    ```json theme={null} theme={null}
    {
      "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
      "tokenOut": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      "amountIn": "1000000000",
      "slippageBps": 100,
      "chainId": 8453
    }
    ```

    **Submit:**

    ```json theme={null} theme={null}
    {
      "quoteId": "...",
      "user": "0x...",
      "unwrapNativeOut": true
    }
    ```

    **Approval:** standard ERC-20 approve of the router for `amountIn`, or use `permit`.

    The router pulls USDC, swaps to WETH internally, then unwraps and sends ETH to `user` in the same transaction.
  </Tab>

  <Tab title="ETH → WETH (or WETH → ETH)">
    A pure wrap or unwrap also goes through the aggregator. The router uses a no-op routing path — there's no swap math involved, just a `deposit()` or `withdraw()` call against WETH.

    **Wrap:**

    ```json theme={null} theme={null}
    {
      "tokenIn":  "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      "tokenOut": "0x4200000000000000000000000000000000000006",
      ...
    }
    ```

    Then on `/submit` set `useNativeIn: true`.

    **Unwrap:**

    ```json theme={null} theme={null}
    {
      "tokenIn":  "0x4200000000000000000000000000000000000006",
      "tokenOut": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      ...
    }
    ```

    Then on `/submit` set `unwrapNativeOut: true`.
  </Tab>

  <Tab title="ERC-20 → ERC-20">
    No native handling. Don't set either flag. The router pulls `tokenIn`, swaps to `tokenOut`, sends to the user.

    **Approval:** required (or use `permit`).
  </Tab>
</Tabs>

## Common mistakes

<CardGroup cols={2}>
  <Card title="Forgot useNativeIn" icon="circle-exclamation">
    `/submit` response has `value: "0"` even though `tokenIn` was the native sentinel. Cause: you didn't set `useNativeIn: true` on `/submit`. The API errs on the side of safety and assumes you might have changed your mind.
  </Card>

  <Card title="Sending msg.value with an ERC-20 swap" icon="triangle-exclamation">
    The router rejects any non-zero `msg.value` when `useNativeIn` is `false`. If your wallet is sending ETH along, double-check you didn't carry over `value` from a previous swap.
  </Card>

  <Card title="Approving WETH unnecessarily" icon="lock">
    For an `ETH → ERC-20` swap with `useNativeIn: true`, the user does not need to approve WETH. The router handles the wrap from `msg.value` and the resulting WETH never leaves the router contract.
  </Card>

  <Card title="Missing unwrapNativeOut" icon="ethereum">
    User receives WETH instead of ETH because `unwrapNativeOut` was omitted on `/submit`. Always set it explicitly when you want native ETH back.
  </Card>
</CardGroup>

## Why both quote and submit need the flag

The aggregator detects native intent on `/quote` from the sentinel and sets `routePlan.nativeIn` / `routePlan.nativeOut`. But `/submit` requires you to re-confirm with the explicit flag because:

1. The `quoteId` is independent of the user. The same quote can be submitted by different users with different preferences.
2. Some integrators want to auto-wrap on the user's behalf, e.g. always pull ERC-20 WETH from the user even when the quote was for native ETH.

Always pass `useNativeIn` / `unwrapNativeOut` explicitly on `/submit` to remove ambiguity.
