Odos

🧠 How the Odos Parser Works

The Odos parser in the-parsoor is a modular, multi-version system that extracts swap-related data from Odos's routers deployed across various chains. It identifies and parses three distinct contract types:

  • V1 Router

  • V2 Router

  • Limit Order Router

Each of these contract versions is parsed in isolation using dedicated logic and ABIs. Let’s explore the architecture and code patterns used in depth.


πŸ“ Directory Structure

src/lib/Odos/
β”œβ”€ abis/                     ← ABIs for router versions
β”‚  β”œβ”€ V1Router.json
β”‚  β”œβ”€ V2Router.json
β”‚  └─ LimitOrderRouter.json
β”œβ”€ parsers/                 ← Parsing logic per router version
β”‚  β”œβ”€ RouterV1.ts
β”‚  β”œβ”€ RouterV2.ts
β”‚  └─ LimitOrderRouter.ts
β”œβ”€ contracts.ts             ← Deployment info, event hashes, and ABIs
└─ index.ts                 ← Parser class implementing OpenRep’s parser interface

πŸ”— contracts.ts β€” The Router Registry

This file defines:

  • Contract addresses per chain

  • Events emitted by each router

  • Associated ABIs for decoding those events

Each router version is represented using an enum (CONTRACT_ENUM), and its event signatures are listed in EVENT_ENUM.

Key Elements:

// V2 Event signature + ABI interface
[V2_SINGLE_SWAP]: {
  abi: new ethers.Interface([
    "event Swap(address sender,uint256 inputAmount,address inputToken,uint256 amountOut,address outputToken,int256 slippage,uint32 referralCode)"
  ])
}

Why it matters:

This setup allows ProtocolHelper to dynamically decode logs just by checking the topic hash.


🧱 index.ts β€” The Parser Entry Point

This is the class that integrates the parser into the OpenRep system.

What it does:

  • Implements IProtocolParserExport

  • Registers a protocolIdentifier from config/protocols.ts

  • Uses ProtocolHelper.txnToIsListenerContract() to route the transaction to the correct sub-parser

  • Supports async behavior for future compatibility

Code Overview:

if (ProtocolHelper.txnToIsListenerContract(tx, CONTRACT_ENUM.V2_ROUTER, contracts)) {
  actions.push(...RouterV2Parser.parseTransaction(tx));
}

This keeps all router-specific logic decoupled and modular.


🧠 Parsing Logic Per Router

βœ… V2 Router β€” RouterV2.ts

Handles the latest swap logic and detects two kinds of events:

  • Swap β†’ single-token swap

  • SwapMulti β†’ multi-token route swap

const hasSingleSwap = transaction.logs.find(
  (log) => log.topics[0] === EVENT_ENUM.V2_SINGLE_SWAP
);

if (hasSingleSwap) {
  actions.push(this.parseSingleSwap(hasSingleSwap));
}

Returned Action Types:

  • ISingleSwapAction

  • IMultiSwapAction


βœ… V1 Router β€” RouterV1.ts

Supports legacy Odos swaps. Event structure is more complex, containing outputs as a nested struct:

"event Swapped(address sender,uint256[] amountsIn,address[] tokensIn,uint256[] amountsOut,(address tokenAddress,uint256 relativeValue,address receiver)[] outputs,uint256 valueOutQuote)"

The parser differentiates between:

  • Single swap (1 input, 1 output)

  • Multi swap (multiple inputs/outputs)

Design Pattern:

if (tokensIn.length === 1 && outputs.length === 1) {
  return this.parseSingleSwap(parsedLog);
}

Returned Action Types:

  • ISingleSwapAction

  • IMultiSwapAction


βœ… Limit Order Router β€” LimitOrderRouter.ts

Parses on-chain fill logs from limit orders submitted via Odos.

Event Types:

  • LimitOrderFilled

  • MultiLimitOrderFilled

const hasLimitOrderFill = transaction.logs.find(
  (log) => log.topics[0] === EVENT_ENUM.LIMIT_ORDER_FILL
);

Returned Action Types:

  • ISingleSwapAction

  • IMultiSwapAction

Each order fill is mapped to a swap action with relevant:

  • fromToken, toToken

  • fromAmount, toAmount

  • sender, recipient


πŸ§ͺ Runtime Flow: How a Tx is Parsed

  1. A transaction is passed to the Odos parser class (index.ts)

  2. The class uses ProtocolHelper to determine which router the transaction was sent to

  3. Once matched, the class calls the appropriate parseTransaction() from the correct router parser

  4. The returned list of ITransactionAction[] is sent downstream to OpenRep scoring logic


βœ… Benefits of This Architecture

Feature
Benefit

Modular Parsers

Each contract version has isolated logic and tests

Enum-based Contracts

Easy to add more routers or events

ProtocolHelper usage

Shared logic for log decoding and routing

Scalable

Adding v3 routers or new chain support is plug-and-play

Typed actions

Ensures all outputs conform to OpenRep’s score engine format

Last updated