MORAIN.
How it works

One Book, Three Checks

Read the chain, ask each pool what this order can receive, then have the contract enforce the minimum you signed. Those are the three steps; none requires trusting the interface.

1 · Read the chain

DexScreener tells the engine which pools exist. Prices and liquidity come straight from chain 4663. Concentrated pools are read from their own state; Uniswap v4 prices come from singleton storage because v4 has no separate pool contract.

slot = keccak256(abi.encode(poolId, 6))
sqrtPriceX96 = extsload(slot) & ((1 << 160) - 1)

About half the live pools are v4. An indexer once converted their cross-equity prices through its own rate, creating apparent spreads of three to four percent. Reading the singleton directly reduced the widest observed SPY spread from 4.74% to 1.25%.

2 · Ask the pools

A price means little without an order size. A model that stops at the current tick overstates output by about 0.16% in a one-tick-spacing pool. Venue differences can be around 0.01%, making that modelling error far larger than the spread under study.

Morain quoter asks the pool itself. It invokes the real swap, then reverts from the callback with the quote instead of paying. No transaction settles and no signature is needed. One eth_call prices the entire book, including each pool’s usable depth.

3 · Enforce the fill

The router receives the input, follows the route, and measures the output as a balance change. It deducts the protocol fee before comparing the result with your signed minimum. A shortfall reverts the transaction.

uint256 got = IERC20(tokenOut).balanceOf(address(this)) - outBefore;
if (bps != 0) got -= (got * bps) / 10_000;
if (got < minOut) revert SlippageLimit(got, minOut);

A concentrated pool may stop accepting input when liquidity runs out. The router rejects an order if any input would remain there. A partial fill is a revert, never a partial success.

Contracts

Deployed at block 50,072,426. The contract caps its protocol fee at 0.30%; the cap cannot be raised. Ownership changes require two steps, preventing a mistyped address from taking control immediately.

Deliberate limits

The caller provides Hop.pool; the router does not check it against a factory. Instead, it guarantees that a pool receives only funds from this call, up to that hop’s amountIn. A bad pool choice can harm only the signer of that route.

Buy or sell through one call

The same call handles buys and sells by reversing the tokens. Routes support up to three hops and can bridge an equity without a direct pool in the chosen currency. A second hop is used only when it improves on the direct route by more than ten basis points, accounting for its extra fee and liquidity risk.

Uniswap v2 pools are intentionally excluded. None are live on this chain, and applying a constant-product formula to a Solidly-style curve would understate its output.

Splitting an order across pools

A large order moves farther along one pool’s curve and receives a worse price at the tail. Distributing that order among pools uses flatter portions of several curves. For an order large enough to exhaust one pool, the difference can approach thirty percent more of the asset for the same spend.

Splits use a separate contract because multiple legs are not the same call as one route. It executes v3 legs before the singleton lock and v4 legs inside it, then measures one combined balance change. minOut applies to the total, not each leg; set it with the least liquid leg in mind, rather than an average.

The allocation creates the improvement. Arbitrary splitting can perform worse than a single route. The engine quotes every pool across a grid of sizes, solves for the shares, and splits only when the result clearly exceeds the best single route.

The contracts have not been audited. They hold no funds between transactions, and the source is public. Those are the limits of the assurance we can give today.

Venues

Six Venues, Checked On-Chain

The engine identifies an AMM by querying its pools, not trusting an indexer version label. Two venues have no version tag; treating them as constant-product was wrong. One reports raw balances through getReserves, which are not a price.

VenueAMMPrice fromRoutableNote
Uniswap v3v3slot0()yesDeepest USDG books on the chain.
Uniswap v4v4extsload on the singletonquote and executeQuotes and execution use the V4 quoter and router. See the current addresses in the contract registry.
Ramsesv3slot0()yesRenamed callback, dispatched without an adapter.
Gigav3slot0()yesBounded liquidity — stops absorbing around $124k.
Upv3slot0()yesProxy pools, equity-paired only.
AlandaleAlgebraglobalState()yesDynamic fee. getReserves is not a price here.

Why one execution path works

These v3 descendants share a swap signature and callback structure; only the callback name changes. The router’s fallback handles those selectors, letting Ramses, Giga, and Algebra use the Uniswap execution path. The hop fixes what the callback may pay, regardless of what the pool requests.

What fork tests cannot cover

These tokenised equities are Stylus contracts: WebAssembly rather than EVM bytecode. Foundry’s revm cannot execute them, while Up and Alandale pools are paired only with equities. Fork tests therefore cover ordinary ERC-20 pairs; live-chain simulation covers the venues carrying the actual product:

node verify/probe_venues.mjs

This script simulates a swap through the deployed router, using one pool from each venue and current mainnet state. State overrides provide balances and allowances. It requires no funds and transfers nothing.

Verify

Verify Every Number

Every published figure is derived from a command you can run. If your calculation disagrees with the site, the site is wrong.

The whole suite
bash verify/all.sh

The checks cover encoder and keccak output against cast, the canonical registry, venue execution, partial-fill rejection, and a real trade dry-run.

The book
node verify/canon.mjs

Resolves each ticker to its canonical contract, excludes pools reporting billions in depth against negligible volume, and prints the venue table.

Depth limits
node verify/partial_fill.mjs

Finds a pool’s input limit, then confirms that the router rejects an order beyond it instead of filling only part of it.

The encoder
node verify/encode_check.mjs

Compares every selector, topic, and calldata payload built here byte for byte with Foundry. A mismatch fails before the app can send malformed data.

A live round trip

A live round trip exchanged 5 USDG for 0.02275283 NVDA, then 0.02 NVDA for 4.392261 USDG. Both directions used the same contract and app routing code. The buy matched its quote exactly; the sell differed by 0.002%. The router retained nothing after either fill.

What remains unproven

There is no audit. We state that explicitly.

Integrate

Use the HTTP API

Read verified assets, compare executable quotes, build unsigned transactions, and check settled fills through the same public endpoints used by the interface.

Request a quote

GET /api/v1/quote?tokenIn=USDG&tokenOut=SPY&amountIn=10

Verify a fill

GET /api/v1/receipt?tx=0x...

The API returns routes and unsigned transaction data. A wallet remains responsible for review, approval, and signing.

About

One Layer Across Existing Venues

Morain holds no liquidity. It reads the pools already on Robinhood Chain and presents them as one executable book.

On chain 4663, tokenised equities trade through roughly 170 pools across nine venues. Quotes use dollars, wrapped ether, or other equities, and their prices can differ.

A visible price gap is only a starting point. To trade it, you must know how much each pool can fill and enforce the worst outcome you will accept. That is the protocol’s job.

What exists today

The depth engine reads live pools on-chain. The quoter lets each pool calculate its own output. The router checks the actual fill. All three are deployed, verified, and reproducible from the repository.

What does not

No audit, invented token utility, unsupported partnerships, investor list, or unattributed press quotes. Claims on this site are backed by something you can open.

Changelog

Release History

Deployments and measurements, newest first. Each entry points to an address, transaction, or reproducible command.

Router and quoter live
Deployed and verified

The router and quoter were deployed on chain 4663 at block 50,072,426 and verified on Blockscout. The protocol fee was set to zero.

First fill
5 USDG into NVDA

The fill matched its quote exactly and left no balance in the router.

v4 priced on-chain
extsload on the singleton

Reading v4 state on-chain removed the indexer cross-rate from about half the live pools. The widest measured SPY spread moved from 4.74% to 1.25%.

Venue classification fixed
Ask the pool, not the label

Up and Alandale arrive without version tags and were mistakenly treated as constant-product. Alandale uses Algebra; its getReserves output is not a price.