Docs

Scuro is three things: rules that live in your browser, a hook that settles a pool in batches, and a pool of notes the trades can come out of. This page is the whole mechanism, and a row-by-row statement of what on this site is real.

The shape of it

A watch hook is a rule in the plainest sense: a thing to read, a line, and a side. It is kept in this browser, sealed, and evaluated here. The chain never learns it exists; the only thing it ever sees is a read.

The batch hook is a Uniswap v4 hook. A pool under it cannot be swapped directly: orders are cast into a batch, and a batch is settled as one swap of the residual at one price. The ledger records the net, not the parts.

The shade is a pool of notes: commitments in a Poseidon tree, spent by proof. A cast can be paid from a note; the output goes back to a one-time key. The batch is then settled against the pool, and the pool is nobody.

Watch hooks: where a rule lives

The browser generates an AES-GCM key and marks it non-extractable; it lives in IndexedDB and can be used but never read. The set of rules and the last two hundred matches are one ciphertext in localStorage. A copied profile folder is ciphertext. A script that reads localStorage gets ciphertext.

Every thirty seconds, while the tab is visible, all enabled rules become one Multicall3 call: balances, slot0 words, liquidity words. The RPC sees addresses and slots. It does not see a name, a line, a side, or that anything fired.

A rule fires on a crossing, not a level: the tick on which the value steps over the line. The first read after a rule is set only records where things stand, so a rule drawn below today's balance does not fire the moment it is made.

// one tick
reads  = rules.map(toCall)        // address + slot, nothing else
values = multicall3(reads)        // one eth_call
for rule in rules:
  if crossed(rule.last, values[rule], rule.line, rule.side): fire(rule)
  rule.last = values[rule]
seal(rules)                       // AES-GCM, key never leaves IndexedDB

To move rules to another browser, export them under a passphrase: PBKDF2-SHA-256 at 310 000 rounds derives the key, and the file is ciphertext without it. There is no account to recover from. That is the point and it is also the cost.

The batch hook: one swap per batch

A pool under the hook refuses direct swaps in beforeSwap unless the caller is the hook itself. Orders are cast into the open batch with a size and a side. When the window closes, anyone may settle: buys and sells are matched against each other at the pool's current price, fee-free, and only the residual is swapped through the pool as a single swap. Each side receives one blended price.

What this hides: your footprint on the pool, since its price, its Swap event and its storage only ever see the batch's residual; what each order paid, since a cast is not a price point; and who traded against whom. What it still shows: the cast itself, unless it comes from the shade, and the batch total, residual and output on the ledger.

Two orders that match each other exactly leave the pool's price and liquidity where they were. The batches page lets you run that settlement against a live pool today; once our hook is on chain it reads the hook's own events instead.

The shade: where the trade comes from

Shade: deposit a token into the pool of notes. What you hold is a commitment in a Merkle tree, encrypted to your own viewing key, that nobody can spend but you. Cast: prove you own a note and cast its value into the open batch; the pool, not you, is the address the batch sees, and the output is already addressed to a fresh one-time key. Settle: anyone closes the batch. Surface: spend the output note to any address, or keep it shaded and cast again.

Hidden: who cast, since the spender is a nullifier; who received, since the output goes to a one-time key; balances and transfers inside the pool. Still visible: shield and unshield amounts in and out of the pool, the size of a shielded cast, and the set of addresses that have ever shielded.

Wallets and reads

Reading a chain needs no wallet, so the site asks for none. Pools, hooks and batches are read from our own index of Robinhood Chain and, for watch hooks, straight from a public RPC in your browser. A wallet, when one is needed, is discovered through EIP-6963, connected for one transaction and not remembered: reload and it is gone.

What is real today

Privacy that does not say what it leaks is marketing, and a roadmap that does not say what is shipped is worse. Each row below says which it is.

PieceStatusWhere
Watch hooksRunning in your browserThis site, /hooks. AES-GCM vault, Multicall3 every 30 s against the public RPC.
Pools and hook permissionsLiveOur own index of Uniswap v4 on Robinhood Chain; permissions decoded from the hook address.
Batch settlementSimulated on live prices/batches computes the netting in your browser. Our hook contract: designed, being deployed on Robinhood Chain; its address will be listed here.
The shade (notes, proofs)In designGroth16 circuit and note pool specified; nothing deployed, no proving key.
AuditNoneNothing here has been audited. Treat every contract as experimental.
$SCUROLaunchingRobinhood Chain via Pons. The only contract address is on /token.

Roadmap

Now. Watch hooks live; pools and permissions live; batch settlement simulated on live pools; token live on Pons.

Next. Our batch hook and its gate deployed on Robinhood Chain with a first market under it; the batches page reading its events; a relayer so a shielded cast never links your wallet.

Then. The shade: public Groth16 ceremony anyone can contribute to, the note pool, one-time keys; private liquidity; hooks that act, so a rule can fire a cast.

Dates are targets, not promises. Anything that touches the token, fees, buybacks, governance, is written here as the plan and becomes real only when a contract for it is deployed and listed in the table above.