CUTOFF

A stock pool on Robinhood Chain where every order fills at the next Chainlink print. Nobody trades on a price the pool has already seen, so the trade that drains ordinary stock pools cannot be made here.

What it is

Robinhood Chain carries real tokenized stocks, and each one has a Chainlink feed that publishes a new price whenever the market moves about half a percent. On an ordinary pool, that publication is the moment a faster trader buys at the old price and sells at the new one. The pool pays for the difference.

CUTOFF removes the moment. An order is locked when it is placed and priced at the first print published after it. Waiting orders on opposite sides are then matched against each other at that price, so most volume never touches anyone's inventory at all.

The rule

How a fill happens

Anyone can settle. The caller passes the waiting buys, the waiting sells and the round to settle at:

settleBatch([buyIds], [sellIds], roundId)

Both sides are valued at that print. Whatever the two sides have in common is exchanged directly: the buyers' USDG goes to the sellers, the sellers' stock goes to the buyers. The pool's own reserves do not move, they only collect the fee. The remainder of the larger side stays open.

A worked example. A buyer places 2,000 USDG. A seller places 9 NVDA. The feed prints 228.00. The buyer receives 8.7675 NVDA and is done. The seller's remaining 0.2281 NVDA stays open for the next print. The pool's balances change only by the fee: plus 0.80 USDG and plus 0.0035 NVDA.

The first one, on chain

A buy and a sell were placed on Robinhood Chain and left to wait. The next print came 118 minutes later at 229.11705, and this is what the settlement did:

SidePaidReceivedEffective price
Buy1.247092 USDG0.005440315332272303 NVDA229.2316, the print plus 5 bps
Sell0.005443036850697651 NVDA1.246469 USDG229.0025, the print minus 5 bps

The pool held 1.250845 USDG and 0.005443040065119613 NVDA before the settlement, and 1.251344 USDG and 0.005445217279859892 NVDA after it. It gained 0.000499 USDG and 0.000002177214740279 NVDA, which is the fee and nothing else. No inventory was lent to either side, because the two traders were each other's counterparty. The unfilled remainder, 0.003751 USDG on the buy, was not returned and not cancelled: it stayed open for the print after that.

Settlement 0xf9a7a411, the buy 0xa5a00706, the sell 0x237f1a47.

What we measured

Three days of real swaps on Robinhood Chain, bucketed into thirty minute windows, the same rhythm as the feed:

PoolWindows with both sidesVolume that nets out
NVDA / USDG100%86.5%
SPY / WETH100%85.6%
GLD / USDG (thin)13%45.7%

So on the liquid names, most flow can be filled without a market maker taking the other side. A replay of thirty prints with buyers and sellers in every window ended with the provider's balances higher on both sides, the increase being the fee.

86.5%of NVDA volume nets out inside one print window
0stale-price pick-off, by construction
0.05%fee per order, a fifth of it to whoever settles

Fees and the bounty

Each fill takes 0.05% of the input. Four fifths stays with the pool, which is what a liquidity provider earns. One fifth goes to whoever sent the settling transaction, which is what pays for someone to press the button. There is no protocol fee and no owner.

Using it

Trading

Providing liquidity

Contract reference

One contract, no owner, no upgrade path. Source: Cutoff.sol.

FunctionWhat it does
submit(bool usdgIn, uint256 amountIn)Places an order that fills only against other orders.
submitTo(bool usdgIn, uint256 amountIn, bool poolMayFill)Same, but may also be filled by the pool when nobody takes the other side.
settleBatch(uint256[] buys, uint256[] sells, uint80 roundId)Matches the two sides at that print. Pays the caller a fifth of the fee.
settle(uint256 id, uint80 roundId)Fills one order from the pool's reserves. Reverts with OrdersOnly() unless the order allowed it.
addLiquidity(uint256 usdg, uint256 stock, uint256 minShares)Deposits both sides and mints shares.
removeLiquidity(uint256 shares, uint256 minUsdg, uint256 minStock)Burns shares and returns the pro rata reserves.
versusHolding(address)Position value and the value of holding the same deposit, both in USD with 18 decimals.
orders(uint256)owner, usdgIn, poolMayFill, amountIn, submittedAt, closed, roundId, amountOut, filledIn.

Errors

Running a matcher

Settling is open to anyone and pays a fifth of the fee. The repository ships a small one that reads the chain with plain JSON-RPC and sends with cast:

RPC_URL=https://rpc.mainnet.chain.robinhood.com \
POOL=<pool address> KEEPER_KEY=<private key> node keeper.mjs

It groups the open orders into buys and sells, calls settleBatch at the latest print, and then fills anything left over that opted into the pool.

Limits and risks

Waiting is the price. An order does not fill until the feed prints again, and the feed does not run on a clock. Measured across 14 consecutive rounds on the live NVDA feed, every print landed on a move of 0.501% to 0.601%, and the gaps between them ran 7, 11, 13, 25, 38, 44, 49, 53, 54, 112, 132, 382 and 419 minutes. Median 49 minutes, worst case just under seven hours. A flat tape means a long wait, a weekend means Monday's first print, and if nothing takes the other side it waits longer still.

Verify it yourself

Open the app ยท Back to the site