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 setsactive = false without shifting indices.
DEX Types
| Constant | Value | Protocol Style | Interface |
|---|---|---|---|
DEX_TYPE_UNIV3 | 0 | Concentrated liquidity | IUniswapV3Quoter |
DEX_TYPE_AMM_V2 | 1 | Constant product | IAmmRouter |
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
Quote Dispatch
Whenfind_best_route is called, the contract iterates over all active DEXes
and dispatches to the appropriate quoter based on DEX type:
Uniswap V3 (DEX_TYPE_UNIV3)
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.AMM V2 (DEX_TYPE_AMM_V2)
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.Public Methods
initialize() -> Result<()>
initialize() -> Result<()>
Set the caller as owner and seed the default routing tokens (WETH, USDC).
Can only be called once.
add_dex(dex_address, dex_type) -> Result<U256>
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).
remove_dex(index) -> Result<()>
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).
add_routing_token(token) -> Result<()>
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.
remove_routing_token(token) -> Result<()>
remove_routing_token(token) -> Result<()>
Remove a routing token using swap-and-pop. Owner only.
find_best_route(token_in, token_out, amount_in) -> Result<(U256, Vec<Address>, Vec<u32>)>
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.
compare_routes(token_in, token_out, amount_in) -> Result<(U256, U256)>
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.dex_count() -> U256
dex_count() -> U256
Total number of DEXes ever registered (including soft-deleted).
get_dex(index) -> (Address, U256, bool)
get_dex(index) -> (Address, U256, bool)
Read a DEX entry:
(address, type, active).routing_token_count() -> U256
routing_token_count() -> U256
Number of currently active routing tokens.
Route Selection Example
Given two registered DEXes (Uniswap V3 and Camelot V2) and routing tokens WETH + USDC, a call tofind_best_route(ARB, GMX, 1000e18) would evaluate:
amountOut is selected.
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.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