ZirgCore
Connect Wallet
Docs

How the core works.

Markets are not numbers. They are executable paths.

A quote is only worth what the pool behind it can deliver. ZirgCore reads liquidity directly from registered on-chain markets, simulates the trade with the pool's own math, and returns an executable route — or a verdict that says why not. Nothing displayed is a placeholder: values come from RPC calls, registered pool contracts, the explorer or a named indexer, and every result carries its block number and source.

Inspection pipeline

  1. Tokendecimals(), symbol(), name(), totalSupply() via Multicall3 (bytes32 fallbacks). No decimals → UNSUPPORTED MARKET.
  2. Discovery — every registered factory is asked for the pool of (asset, quote) for each quote token (USDG, WETH) and each V3 fee tier (0.01%, 0.05%, 0.3%, 1%) in one multicall.
  3. State — V2: getReserves(); V3: slot0(), liquidity(), tickSpacing() and the pool's real token balances. The L2 block stamp is read in the same HTTP batch.
  4. USD referenceUSDG counts as 1 USD; WETH is priced from its deepest USDG pool at the same read. Pools quoted in anything else keep quote units and are marked "no USD reference".
  5. Depth ladder — a BUY of $100, $500, $1,000, $2,500, $5,000, $10,000, $25,000 is simulated on the deepest pool (constant product for V2, a tick-by-tick SwapMath walk for V3). PARTIAL and INSUFFICIENT_LIQUIDITY are reported as such.
  6. Verdict — produced from the numbers above and printed with its reasons.

Verdicts

DEEPRegistered depth ≥ $1,000,000 and a $10,000 execution moves the price ≤ 0.5%.
HEALTHYDeepest pool ≥ $50,000 and a $1,000 execution moves the price ≤ 1% with a full fill.
THINThe $1,000 reference exceeds the 1% limit, fills only partially, or the pool is below the HEALTHY floor.
FRAGMENTEDTwo or more live pools, the deepest holds < 60% of total depth, and no single pool supports the reference size within the limit.
UNVERIFIEDLiquidity exists but cannot be sized (no USD reference), comes from an unregistered factory, or the simulation could not run.
NO LIQUIDITYNo registered pool holds reserves on both sides.

Price impact strips the LP fee first (Uniswap convention), so it measures pool movement, not the fee. Thresholds live in src/config/thresholds.ts.

Route engine

For tokenIn → tokenOut the engine reads every direct pool plus two-hop paths through the chain's intermediates (WETH, USDG), same venue family per path so one router executes it atomically. Each candidate reports output, gas (a real eth_estimateGas when a recipient is known), price impact, the shallowest hop's USD depth, a confidence score and hop count.

Route verdicts: REJECTED when impact > 5%, a hop fills partially, or a pool failed verification; THIN when impact > 1% or depth < $50,000; otherwise HEALTHY. Ranking is executable first, then verdict, then output — the highest output is not selected when its liquidity quality is unsafe, and the response says which route was skipped and why.

Execution

Calldata is encoded for the venue's verified router — Uniswap V3 → 0xcaf681a66d020601342297493863e78c959e5cb2; Uniswap V2 → 0x89e5db8b5aa49aa85ac63f691524311aeb649eba; Pons curve → the curve contract itself — after checking on-chain that the router's factory() (and WETH9()) bindings match the registered factory. Before signing you see input, expected output, minimum received, route, DEX, price impact, estimated gas, deadline, slippage and network. ERC-20 inputs need an exact-amount approval first; the native coin is wrapped by the router. The wallet signs and broadcasts; ZirgCore only watches the receipt.

Catalog and venues

The markets list is the chain's catalog read in one batched pass: the quote tokens, the official tokenized-stock registry (live when reachable, otherwise the dated snapshot that ships with the app — every ticker is re-verified against its ERC-20 contract before it is listed), and ecosystem tokens launched by sibling projects through the Pons V2 launchpad. Three venue families are read: Uniswap V3 pools, Uniswap V2 pairs and Pons bonding curves (a launcher token publishes curve(); the curve counts only when its factory() is the registered launch factory). Curve depth is the quote it physically holds — the phantom quote is excluded — and curve execution calls buy/sell on the curve contract itself with the same fee and creator-tax math as the verified source.

Transparency

Every market result prints SOURCE / CHAIN / BLOCK / UPDATED. Indexer values (24h volume, pool age) are labelled with the indexer's name and never feed a verdict. When something cannot be fetched the UI prints Unavailable, No verified route, RPC unavailable or Unsupported market — never a placeholder.

Adding a chain

Add one entry to src/config/chains.ts: id, public RPC, explorer API, Multicall3, wrapped native, quote tokens, route intermediates and the venue addresses. Set RPC_URL_<id> for a private endpoint. Adapters enable themselves when factories are listed and re-verify routers at runtime, so an address that does not answer like the expected contract stays read-only.

Adding a liquidity adapter

Implement LiquidityAdapter (src/adapters/liquidity/types.ts): discoverySpecs, getPoolState, getLiquidity, getQuote, getPriceImpact, buildTransaction, verifyRouter. Register it in src/adapters/liquidity/index.ts. The market inspector, route engine and API pick it up automatically.

Security

  • No seed phrases, no private keys, no server-side signing.
  • The browser talks to the chain only through a read-only relay with a method allow-list.
  • Contract reads are eth_call only; writes happen exclusively through the reviewed execution flow.
  • Addresses, chain ids, decimals and transaction targets are validated; unknown or unverified contracts, high slippage, high impact and low liquidity are flagged before signing.