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

# Route Optimizer

> Multi-DEX route comparison with fee-aware scoring

The Route Optimizer is a Stylus contract that evaluates swap routes across
multiple registered DEXes to find the best output amount. It supports Uniswap V3
concentrated liquidity pools and AMM V2-style constant product pools, with
single-hop and two-hop routing through configurable intermediate tokens.

## DEX Registry

DEXes are stored in a dynamic registry using the **indexed mapping + soft-delete
pattern**. Each entry has an address, a type discriminant, and an active flag.
Removal sets `active = false` without shifting indices.

```rust theme={"theme":{"light":"dracula","dark":"dracula"}}
sol_storage! {
    #[entrypoint]
    pub struct RouteOptimizer {
        address owner;
        uint256 dex_count;
        mapping(uint256 => address) dex_addresses;
        mapping(uint256 => uint256) dex_types;
        mapping(uint256 => bool) dex_active;
        address[] routing_tokens;
    }
}
```

### DEX Types

| Constant          | Value | Protocol Style         | Interface          |
| ----------------- | ----- | ---------------------- | ------------------ |
| `DEX_TYPE_UNIV3`  | `0`   | Concentrated liquidity | `IUniswapV3Quoter` |
| `DEX_TYPE_AMM_V2` | `1`   | Constant product       | `IAmmRouter`       |

The registry is capped at **20 DEXes** (`MAX_DEXES`).

## Routing Tokens

Routing tokens are intermediate assets used for two-hop paths (e.g.
`USDC -> WETH -> ARB`). On initialization, the contract seeds two defaults:

* **WETH** -- `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`
* **USDC** -- `0xaf88d065e77c8cc2239327c5edb3a432268e5831`

Additional tokens can be added up to a cap of **50**.

## Quote Dispatch

When `find_best_route` is called, the contract iterates over all active DEXes
and dispatches to the appropriate quoter based on DEX type:

<AccordionGroup>
  <Accordion title="Uniswap V3 (DEX_TYPE_UNIV3)">
    **Single-hop:** Calls `quoteExactInputSingle` for each of the four standard
    fee tiers (`100`, `500`, `3000`, `10000` bps).

    **Two-hop:** For each intermediate routing token, encodes a packed path and
    calls `quoteExactInput` across all fee tier combinations (`4 x 4 = 16`
    combinations per intermediate token).

    The best output across all tiers and hops wins.
  </Accordion>

  <Accordion title="AMM V2 (DEX_TYPE_AMM_V2)">
    **Single-hop:** Calls `getAmountsOut` with a direct `[tokenIn, tokenOut]`
    path.

    **Two-hop:** For each intermediate routing token, calls `getAmountsOut` with
    a `[tokenIn, intermediate, tokenOut]` path.

    AMM V2 pools have flat fee structures, so there are no fee tier iterations.
  </Accordion>
</AccordionGroup>

## Public Methods

<AccordionGroup>
  <Accordion title="initialize() -> Result<()>">
    Set the caller as owner and seed the default routing tokens (WETH, USDC).
    Can only be called once.
  </Accordion>

  <Accordion title="add_dex(dex_address, dex_type) -> Result<U256>">
    Register a new DEX quoter/router. Owner only.

    * Rejects zero addresses and reverts if the registry is full (20 DEXes).
    * Returns the new DEX index.
    * Emits `DexAdded(index, dexAddress, dexType)`.
  </Accordion>

  <Accordion title="remove_dex(index) -> Result<()>">
    Soft-delete a DEX by setting `dex_active[index] = false`. Owner only.

    * Reverts if index is out of bounds or already removed.
    * Emits `DexRemoved(index, dexAddress)`.
  </Accordion>

  <Accordion title="add_routing_token(token) -> Result<()>">
    Add an intermediate token for two-hop routing. Owner only.

    * Rejects zero addresses, duplicates, and reverts at the 50-token cap.
  </Accordion>

  <Accordion title="remove_routing_token(token) -> Result<()>">
    Remove a routing token using swap-and-pop. Owner only.
  </Accordion>

  <Accordion title="find_best_route(token_in, token_out, amount_in) -> Result<(U256, Vec<Address>, Vec<u32>)>">
    Find the route with the highest output amount across all active DEXes.

    Returns `(amountOut, tokenPath, feePath)`:

    * `tokenPath` -- ordered list of token addresses in the route.
    * `feePath` -- Uniswap V3 fee tiers for each hop (empty for AMM V2).
    * Reverts with `"no route found"` if no DEX returns a quote.
  </Accordion>

  <Accordion title="compare_routes(token_in, token_out, amount_in) -> Result<(U256, U256)>">
    Simplified comparison that returns `(best_dex_index, best_amount_out)` using
    direct quotes only (no multi-hop). Useful for quick price checks.
  </Accordion>

  <Accordion title="dex_count() -> U256">
    Total number of DEXes ever registered (including soft-deleted).
  </Accordion>

  <Accordion title="get_dex(index) -> (Address, U256, bool)">
    Read a DEX entry: `(address, type, active)`.
  </Accordion>

  <Accordion title="routing_token_count() -> U256">
    Number of currently active routing tokens.
  </Accordion>
</AccordionGroup>

## Route Selection Example

Given two registered DEXes (Uniswap V3 and Camelot V2) and routing tokens
WETH + USDC, a call to `find_best_route(ARB, GMX, 1000e18)` would evaluate:

```
Uniswap V3:
  Direct: ARB->GMX @ 100bps, 500bps, 3000bps, 10000bps
  Via WETH: ARB->WETH->GMX @ 16 fee combos
  Via USDC: ARB->USDC->GMX @ 16 fee combos

Camelot V2:
  Direct: ARB->GMX
  Via WETH: ARB->WETH->GMX
  Via USDC: ARB->USDC->GMX
```

The route returning the highest `amountOut` is selected.

<Note>
  Private helper methods (`quote_univ3`, `quote_amm_v2`) live in a separate
  `impl` block because they accept `&mut` references that are not
  ABI-compatible. This is a Stylus SDK requirement -- only the `#[public]` block
  generates ABI exports.
</Note>

## Test Coverage

The contract has 38 tests covering:

* DEX registry CRUD (add, remove, soft-delete verification)
* Routing token management (add, remove, duplicate rejection, cap enforcement)
* UniV3 single-hop and multi-hop quote dispatch
* AMM V2 direct and two-hop quote dispatch
* Best route selection across multiple DEXes
* Access control on all owner-only methods
* Edge cases: empty registry, all DEXes removed, no route found
