LIQORA live liquidity intelligence
Every call, every formula, every limit

How LIQORA works

LIQORA has no backend, no database, no price feed and no API key. It is a handful of static files talking straight to an Ethereum node — mainnet for crypto, Robinhood Chain for tokenized equities. This page is the whole mechanism — the contracts it calls, the arithmetic it does with the answers, and the places where the number it shows you would differ from a real fill.

01

What "simulate" means here

It means eth_call. That is a real execution of the real EVM, on a real node, against the real current state of the real pool contracts. The same opcodes run, the same pool code executes, the same arithmetic happens as in an actual swap. The only difference is that the result is thrown away instead of written into a block.

So it is not a model, an estimate, or a mock. When LIQORA prices a Uniswap v3 order it calls QuoterV2, and that contract internally calls the pool's own swap() function and reads back what came out. It is the same class of read a DEX front-end does to show you a price before you press Swap.

Nothing moves. No transaction is broadcast, no tokens change hands, no signature is requested, no gas is spent, and nothing on-chain changes. LIQORA contains no swap function and no approval flow. If you act on what it tells you, you go and execute elsewhere — that is where real money is involved, and it is outside this app.

The difference in one table

RealPool reserves and prices · fee tiers · output amount · ticks crossed · gas estimate · the block it was priced at
Not realNo broadcast transaction · no balance changes · no signature · no gas spent · nothing written on-chain
02

The pipeline

One refresh is four network round trips, whatever the token.

head     eth_blockNumber + eth_gasPrice + eth_chainId
         → pins the block every later call is made against

discover 21 calls: symbol / decimals / name, then getPool and getPair
         across 4 fee tiers and 3 venues        (cached — pool addresses never change)

state    slot0 + liquidity + both balanceOf per v3 pool, balances per v2 pair
         → mid prices and pool values

quote    every candidate route at your exact size          ≈ 11 calls
         → ranked by output; the winner is the route

then, in parallel:
         ladder  every route at 4 sizes                    ≈ 44 calls
         split   top 3 routes × 10 chunk sizes             = 30 calls
         curve   winning route at 10 sizes                 = 10 calls

That is roughly 160 eth_calls per view, which the Proof panel on the terminal counts for you. They arrive as four JSON-RPC batches, not 160 requests.

03

Contracts it talks to

Nothing else. No proxy, no aggregator, no vendor.

Robinhood Chain — chain 4663, an Arbitrum Orbit L2. This is where the tokenized equities live and where their liquidity actually is. Uniswap v3 is officially deployed; there is no v2 or SushiSwap.

UniswapV3Factory    0x1f7d7550b1b028f7571e69a784071f0205fd2efa
QuoterV2            0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7
USDG quote asset    0x5fc5360d0400a0fd4f2af552add042d716f1d168

NVDA  NVIDIA          0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC
TSLA  Tesla           0x322F0929c4625eD5bAd873c95208D54E1c003b2d
SPY   SPDR S&P 500   0x117cc2133c37B721F49dE2A7a74833232B3B4C0C
AAPL  Apple           0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9
MSTR  Strategy Inc.   0xec262a75e413fAfD0dF80480274532C79D42da09

Ethereum mainnet — chain 1, for the crypto markets. Uniswap v3, Uniswap v2 and SushiSwap.

UniswapV3Factory    0x1F98431c8aD98523631AE4a59f267346ea31F984
QuoterV2            0x61fFE014bA17989E743c5F6cB21bF9697530B21e
UniswapV2Factory    0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
UniswapV2Router02   0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
SushiSwapFactory    0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac
SushiSwapRouter     0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F

USDC  quote asset   0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
WETH  hop asset     0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

Do not assume canonical addresses. The well-known Ethereum Uniswap addresses have code on Robinhood Chain, but it is not Uniswap — getPool there returns nothing. The real deployment is at the addresses above. Every one was confirmed by reading it from the chain, and every token by reading its own symbol().

Calls are encoded by hand — no ethers, no viem, no library at all. Each function selector is the first four bytes of the keccak-256 hash of its signature, computed rather than copied:

getPool(address,address,uint24)                                   0x1698ee82
getPair(address,address)                                          0xe6a43905
slot0()                                                           0x3850c7bd
liquidity()                                                       0x1a686502
balanceOf(address)                                                0x70a08231
quoteExactInputSingle((address,address,uint256,uint24,uint160))    0xc6a5026a
quoteExactInput(bytes,uint256)                                    0xcdca1753
getAmountsOut(uint256,address[])                                  0xd06ca61f
04

Finding every pool

A Uniswap v3 pool exists at one address per (token A, token B, fee tier) triple, and the factory will tell you which. LIQORA asks for all four tiers — 0.01%, 0.05%, 0.30% and 1.00% — for three pairings:

  • USDC / TOKEN — the direct market
  • WETH / TOKEN — the second leg of a routed trade
  • USDC / WETH — the first leg, and the dollar anchor for everything else

Then it asks the Uniswap v2 and SushiSwap factories for the same three pairs. A zero address means no pool, and that tier is dropped. Whatever comes back becomes the candidate set — direct pools, plus every USDC → WETH → TOKEN path that both legs exist for.

This matters more than it sounds. For long-tail tokens the direct USDC pool is usually a ghost, and the real market is the WETH pair. Pricing only the direct pool would give you a confidently wrong answer.

Token identity is read from the contract too — symbol(), decimals() and name() — so pasting an unknown address behaves exactly like one of the built-in markets. Old tokens that return a raw bytes32 symbol instead of a string are handled.

Pool addresses are immutable, so discovery is cached per token for the session. Only their state is re-read on refresh.

05

Reading pool state

For each v3 pool: slot0() gives the current sqrtPriceX96 and tick, liquidity() gives the in-range liquidity, and balanceOf on both tokens gives what the pool actually holds. For each v2 pair, the two balances are enough — its price is its reserve ratio.

One call is deliberately absent. Uniswap orders a pool's tokens by address, so token0 is simply whichever of the two addresses sorts lower. That is decided locally instead of asking the chain, which drops one call per pool.

Turning sqrtPriceX96 into a price

Uniswap v3 stores the square root of the price, scaled by 296, as an integer. Recovering a human price means undoing both the square and the scaling, and correcting for the two tokens' decimals:

// price of token1, denominated in token0
price = (2**192 * 10**dec1) / (sqrtPriceX96**2 * 10**dec0)

This runs in BigInt from end to end. Doing it in floating point loses precision exactly where it hurts — a token priced at 0.0000037 and a token priced at 78,000 have to come out of the same expression.

An early version of this had the direction backwards. Whether the formula or its reciprocal is correct depends on which of the two addresses sorted lower, and PEPE sorts below USDC. It reported PEPE at $270,647 instead of $0.0000037. The orientation is now derived from the address sort, the same rule the pool itself uses.

06

Pricing the order

Three different venues need three different calls, and each returns the true output for your exact size — not a mid price with a fee subtracted.

Uniswap v3, one hop

QuoterV2.quoteExactInputSingle walks the tick range your order would actually cross. It returns the output amount, the price the pool would be left at, how many initialised ticks were crossed, and a gas estimate. The tick count is the honest measure of how hard the order pushed: crossing one tick is a rounding error, crossing eighty means you ate through the book.

Uniswap v3, two hops

quoteExactInput takes a packed byte path — token, fee, token, fee, token — and chains the swaps, feeding the first pool's output into the second. Its return carries an array of ticks crossed, one per hop, which LIQORA sums.

Uniswap v2 and SushiSwap

getAmountsOut on each router. Constant-product venues have a closed-form answer:

amountOut = (in * 997 * reserveOut) / (reserveIn * 1000 + in * 997)

The 997/1000 is the 0.30% fee. LIQORA could compute this locally from the reserves, but it asks the router instead so that every number on the page has the same provenance: an on-chain call.

Every candidate is quoted at your size in a single batch, then ranked by output. Most fill. Some revert, because the pool cannot supply that much — a revert is a real answer, and those routes are counted at the foot of the venue table rather than hidden.

07

The reference mid

The hardest number on the page to get right.

Every cost figure is measured against a mid price, so a wrong mid poisons the whole page. The problem is that a token has as many mid prices as it has pools, and abandoned pools keep quoting nonsense forever.

LIQORA collects a mid from every venue that prices the token — v3 pools from sqrtPriceX96, v2 pairs from their reserve ratio, WETH-quoted pools multiplied by the ETH anchor — and then picks between them with one rule:

Rank candidates only on the quote asset they hold. How much USDC is in this pool, or how much WETH. Never the token side.

Score a pool by its total value and a broken pool can promote itself: it marks its own token holdings at its own wrong price, reports a huge number, and wins. Scoring only the quote side makes that impossible — dollars are dollars regardless of what the pool believes the token is worth.

The ETH/USD anchor is chosen the same way: whichever USDC/WETH venue holds the most USDC. The panel always names the pool it used, so you can check the choice rather than trust it.

This was the second bug. The first version only considered v3 pools for the mid. PEPE's real depth is a Uniswap v2 pair holding thousands of WETH, while its v3 pools are nearly empty — so the mid came from a dead pool. Candidates now span every venue discovered.

08

Cost vs mid = fee + slippage

The headline cost is what the trade really costs against the reference mid, in basis points:

buy  cost = (fillPrice / mid - 1) * 10000
sell cost = (mid / fillPrice - 1) * 10000

That total is then split into the pool's stated fee and whatever is left, which is the price impact your own order caused. The split is the point. A 0.01% tier looks unbeatable on fee alone, but if it holds no liquidity your order crosses dozens of ticks and the slippage dwarfs the saving. Showing 5 bps fee + 47 bps slippage makes that visible immediately.

Past 1,000 bps the display switches to percentages, and past 1,000,000 bps it shows > 10,000%. Those rows are abandoned pools quoting absurd prices. They are left in the table on purpose — knowing which venues to avoid is worth as much as knowing which one to use.

09

Split routing

When one pool cannot absorb the order cheaply, spreading it across several can beat it. LIQORA takes the three deepest venues, quotes each of them at 10%, 20% … 100% of the order — thirty on-chain quotes — and then allocates ten chunks one at a time, each to whichever venue offers the best marginal improvement.

Greedy allocation is optimal here rather than merely convenient. Each venue's output is a concave function of size: every additional chunk into a pool gets a worse rate than the last. For concave curves, taking the best next step each round produces the best whole allocation on that grid.

The result is then charged for what it costs. Three legs are three swaps, so the gross improvement has to clear the extra gas before LIQORA calls it a gain. It frequently does not, and the panel says no gain instead of dressing up a rounding error as alpha.

Allocations resolve to 10% steps, not a continuous optimum. A finer grid would mean more quotes for a difference that gas would eat anyway.

S

The route quality score

One number, and every point accounted for.

A score is only useful if you can see how it was built, so this one starts at 100 and subtracts named, inspectable penalties. The panel on the terminal prints each line with the figure that produced it.

start                                                    100

Cost vs mid        min(55, costBps / 2)              up to -55
Depth vs order     50x+ 0 | 20x -4 | 10x -8 | 5x -14 | below -20
Venue breadth      5+ 0 | 4 -3 | 3 -6 | 2 -10 | 1 -15
Two-hop route      -4        two swaps, two failure points
Ticks crossed      >60 -6 | >25 -3 | else 0

Cost dominates on purpose: it is the part you actually pay. Depth is measured against your order, not in absolute dollars, so a $2M pool scores well for a $10K order and badly for a $1M one. Breadth is there because a single fillable venue is fragile — if it moves before you trade, you have no fallback.

The score never decides anything on its own. It is a summary of numbers that are all on the page already, and every one of them can be checked in the Proof panel.

10

The impact curve

The winning route is re-quoted on-chain at ten sizes from $1K to $1M and plotted on a log axis. Nothing is interpolated or fitted — every point is its own eth_call.

The shape is the useful part. A deep market stays flat then bends late; a thin one bends almost immediately. The bend is where that market stops absorbing you cheaply, and it is usually nowhere near where a single quote would suggest. The size ladder answers the neighbouring question: at which size does the winning venue change?

11

One block, few requests

Two rules keep a view coherent.

Everything is pinned to one block

The first call fetches the block number, and every subsequent call passes that exact block instead of latest. Without it, a refresh spanning a new block would compare a price from block N against a quote from block N+1 — a difference that looks like an arbitrage and is really a bug. The block is printed on the decision panel and in Proof.

Batches, and one endpoint per refresh

Calls go out as JSON-RPC arrays: about 160 calls become four HTTP requests. The endpoint that answers the first call is pinned for the rest of that refresh, because a different node might not have the pinned block yet. Three public endpoints rotate on failure, and you can point it at your own node in Settings.

If a refresh fails, the last good view stays on screen and the QUOTE age counter keeps climbing — amber past 45 seconds, red past 90. Stale data announces itself rather than vanishing or quietly pretending to be fresh.

12

Verify it yourself

You should not have to take any of this on faith.

The Proof panel on the terminal prints the raw calldata behind the current view with a copy-as-cURL button. Paste one into a terminal and any mainnet node returns the same bytes.

The check that settles it

Read a Uniswap v2 pair's reserves straight from the contract, apply the constant-product formula by hand, and compare against what the router returns for the same input. On the USDC/WETH pair for 25,000 USDC:

reserves          10108951132306 USDC   4050835148640753561913 WETH

computed by hand  9963321513077875279
returned by chain 9963321513077875279   identical, digit for digit

A fabricated number cannot land on that value. It falls out of reserves anyone can read.

A second check

Ask the quoter for an impossible order. A $100 billion buy does not revert and does not return a made-up figure — it returns roughly 8,900 WETH, because that is genuinely what draining the curve gives you. Correct arithmetic, useless trade, and the cost column marks it > 10,000%.

+

What is built on the engine

Everything else on the terminal is the same pipeline, re-aimed.

Markets boardThe whole pipeline run for all twelve markets at your current size, four at a time. Sortable on every column; the star pins to a watchlist kept in your browser.
Change %Real, and honest about its window. Uniswap v3 pools carry their own TWAP oracle, so LIQORA asks observe() for 24h and falls back through 6h, 2h, 1h and 15m until the pool's ring buffer can answer. The label always says which window was used, and a WETH-quoted market is combined with the ETH anchor's own TWAP so the figure is a dollar move.
SpreadDistance between the best and worst fill, measured only across venues within 5 percentage points of the best. Include the abandoned pools and every spread reads "> 10,000%" and tells you nothing. With fewer than two usable venues it reports nothing at all.
Order simulatorYour slippage tolerance against the live quote: minimum received, cost in dollars, and whether the tolerance is even wide enough for the route to clear.
Execution checklistFive pass/fail checks — depth, cost, breadth, freshness, gas share — each showing the number behind it.
Route inspectorClick any venue row for that pool's raw state: address, token order, sqrtPriceX96, tick, in-range liquidity, both balances.
Compare and basketTwo markets side by side, or a whole list of lines priced at once with a total execution cost measured against each market's own mid.
Live tradesReal Swap events from the winning pool, decoded and summarised with buy/sell counts and median size. Public endpoints serve only short recent ranges and refuse anything older; when an endpoint refuses, the panel says so and stays empty rather than showing an invented feed.
AlertsA condition on score, cost, price or venue count, checked whenever that market is repriced. Fires as a toast and, with permission, a browser notification.
ShareA text snapshot, a deep link, or a PNG route card drawn on a canvas from the live route.
13

Limits

Where the number shown would differ from a real fill.

  • It does not trade. No execution, no approvals, no custody, no signatures. That is a design decision, not a missing feature, and the roadmap does not secretly end in a router.
  • A quote is one block old the moment you read it. Price moves between the quoted block and any transaction you send.
  • MEV is not modelled. A sandwich attack on your real transaction would make your fill worse than the quote.
  • Fee-on-transfer tokens. The quoter models the pool, not a token that skims a cut on transfer. Those settle under quote.
  • v2 and SushiSwap gas is a typical constant (120k single-hop, 190k two-hop) and is marked . Those routers expose no gas figure. Uniswap v3 gas comes from the quoter.
  • Split allocations resolve to 10% steps, not a continuous optimum.
  • Only Uniswap v3, Uniswap v2 and SushiSwap are searched. Curve, Balancer, Uniswap v4 and private market makers are not, so "best venue" means best among those three.
  • USDC is assumed to be one dollar. Everything is priced against it.
  • Absurd sizes return real but useless numbers rather than refusing.

Back to the terminal