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
fromconfig/protocols.ts
Uses
ProtocolHelper.txnToIsListenerContract()
to route the transaction to the correct sub-parserSupports 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
RouterV2.ts
Handles the latest swap logic and detects two kinds of events:
Swap
β single-token swapSwapMulti
β 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
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
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
A transaction is passed to the Odos parser class (
index.ts
)The class uses
ProtocolHelper
to determine which router the transaction was sent toOnce matched, the class calls the appropriate
parseTransaction()
from the correct router parserThe returned list of
ITransactionAction[]
is sent downstream to OpenRep scoring logic
β
Benefits of This Architecture
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