Threat model

What Kasumi promises, what it does not, and for each party that could misbehave: what they can do, what they cannot, and what risk remains.

Read an order earlyInsert an order after decryptionAlter or overfill an orderCensor an orderStop a market settling
Public observercannotcannotcannotcannotcannot
Relay operatorcannotcannotcannotcan, provablycan
Matchercannotcannotcannotcancan
drand threshold collusioncancannotcannotcannotpartly
Token issuercannotcannotcannotpartlycan
A participant in the batchcannotcannotcannotcannotpartly
A summary of the sections below, which give the conditions and the residual risk for each cell. The first three columns are the properties Kasumi is built to hold; the last two are about liveness, which v1 does not guarantee.

What Kasumi promises#

Pre-trade intent privacy. From the moment an order is encrypted in the client until the drand round of its epoch is published, nobody can read it: not a public observer, not the relay, not the matcher. The order is verifiable after execution: the batch it belonged to was fixed onchain before decryption, and the settlement contract re-checks every constraint the user signed.

Short form: encrypt intent, verify execution.

What Kasumi does not promise#

  • Hidden settlement. Token transfers and fills are public onchain.
  • Permanent secrecy. After its epoch decrypts, every order in the batch can be read by anyone, filled or not, because the decryption key is public.
  • Anonymous wallets or hidden balances. The owner address is in the order and in the transfers.
  • Transaction privacy of the kind a shielded pool gives.
  • Network-level privacy. The relay sees the IP address a ciphertext came from.

Kasumi is not a mixer and does not make funds untraceable.

Assumptions#

  1. Fewer than a threshold of drand quicknet nodes collude, and the scheme (BLS on BLS12-381, identity-based encryption, age) is not broken.
  2. The client device and its random number generator are not compromised.
  3. Robinhood Chain orders and executes transactions as documented, and its clock is roughly accurate.
  4. The contracts behave as written. They are unaudited.

Adversaries#

Public observer#

Can see: epoch roots, order counts, result hashes, and after settlement all fills and transfers. Through the relay API, after an epoch closes, the ciphertexts and their arrival times. After decryption time, the plaintext of every order in the batch.

Cannot: read an order before its epoch's round, or link a ciphertext to a wallet, market, side or size before then.

Residual: the number of orders in an epoch is visible while it is open. Ciphertext length is nearly constant for EOA signatures but differs for smart-account signatures, which can identify an order as coming from a contract wallet.

Relay operator#

Can see: source IP, arrival time, ciphertext size and count, and which commitments were later cancelled. In the deployed app the relay is hosted on Vercel with state in a Neon Postgres database, so those two providers can see the same request metadata and stored ciphertexts. Wallet login in the terminal goes through Privy, a third party that sees the login identifier (an email address or a wallet address) and the pages it is used on. None of them can read a sealed order.

Cannot: read orders early, change an order (it has no signing key), or add an order to a batch after decryption (the root is anchored before decryption time and the settlement contract checks membership).

Can censor: refuse an envelope, or sign a receipt and then leave the leaf out of the root. The second case is detectable: the receipt plus the published root prove it. The first case is not provable. v1 does not prevent censorship. A user who is refused can use another relay once more than one exists; that is not implemented in v1.

Can add its own orders before the cutoff, like anyone else. It does so blind.

Can fail to commit. See "Key release does not wait for the commitment" below. In the deployed app this does not need malice: the relay is serverless, and the commit is only sent if the instance that accepted the epoch's first order is still alive at the cutoff, or a client is polling, or the once-a-minute cron job happens to run inside the reveal window (15 seconds on mainnet). An RPC failure or an empty gas balance has the same effect.

Can ignore a private cancellation. The user's defence is invalidateNonce onchain.

Matcher#

Can see: every order of an epoch once it decrypts.

Cannot: fill an order outside its signed constraints, fill an order that was not in the committed batch, fill at different prices within a market, send proceeds to an address other than the signed receiver, settle a market it did not publish, or settle a market with a result different from the hash it published for it. The settlement contract checks all of these, per market, at settlement time.

Can replace or withdraw the published result of a market that has not settled yet (amendMarket). This is how it recovers when a participant makes a settlement revert. Every amendment emits an event and the originally published resultHash stays onchain, so a matcher that amends without a failed settlement to explain it is visible.

Can choose, within those limits: which valid orders to include and what clearing price to propose. A matcher that deviates from MATCHING.md still produces a settlement in which every filled user got a price inside their limit and inside the oracle band, but it could favour some orders over others. Anyone can detect this after the fact by running the deterministic matcher on the public batch and comparing result hashes. The contract enforces that what settles is what was published; it does not enforce that what was published follows the allocation rule. That part is auditable by recomputation, not enforced.

Can place its own orders before the cutoff, blind like everyone else, and then decide after decryption which of them to settle. A ladder of its own orders on both sides gives it a free option on the batch. It also has a last look for the whole settlement window against a moving oracle. Both are bounded by every other user's signed limit and oracle bound, and both show up as a deviation from the deterministic result.

Can fill an order for a dust amount when the order's minFillBase is 0, which spends its nonce. Users who care set a minimum fill.

Can decline to settle. The epoch then becomes CANCELLED at the deadline and no order executes. Combined with seeing the decrypted batch, this is a free option to abort an epoch. It cannot be used to steal or to alter fills. The same applies to the owner's cancelEpoch.

The minimum-fill rule in MATCHING.md §6 is a fixed heuristic, not a global optimum. An order with a fill-or-kill or minimum-fill constraint can be dropped where a cleverer search would have filled it.

drand threshold collusion#

If a threshold of drand nodes collude, or the cryptography is broken, they can compute a round's signature early and decrypt every order sealed to that round before the epoch closes. Kasumi has no defence against this. It is the central trust assumption. The damage is loss of pre-trade privacy; funds are not at risk, because execution still needs valid signatures and passes the same contract checks.

If drand stops producing rounds, orders stay sealed, the settlement deadline passes and epochs cancel. Nothing executes.

Oracle#

The reference price bounds the clearing price (market-wide band) and breaks ties between volume-maximising prices. A wrong oracle price can move the clearing price inside each user's own limit, never beyond it. Users can tighten the bound per order with maxOracleDeviationBps.

A stale or zero price halts the market: settlement reverts. Equity feeds stop updating outside market hours, so with a tight staleness limit Stock Token markets do not trade outside those hours.

KasumiChainlinkOracle fails closed. It returns no price when the market is unknown, an answer is not positive, either feed is older than its own limit, a round is dated in the future, a token has no code, the sequencer uptime feed (if configured) reports the sequencer down or restarted within the grace period, or a token flagged as a Stock Token reports oraclePaused() or cannot be probed. It has no minimum or maximum answer bound. Whether a sequencer uptime feed exists on Robinhood Chain has not been verified; without one that check is off.

The matcher reads the oracle when it opens the epoch; the contract reads it at settlement. If the price moves between the two so that a bound no longer holds, the market segment reverts and nothing fills.

Token issuer#

Stock Tokens are upgradeable (beacon proxies) and have a blocklist and a pause mechanism. The issuer does not document them; their behaviour was observed on a fork of mainnet (see DEPLOYMENT.md). A transfer reverts if the sender of the funds, the recipient or the caller is on the registry's blocklist. A token can be paused on its own, and the registry can pause every Stock Token at once. The issuer can therefore change token behaviour, block an address, or pause transfers. If the settlement contract itself were blocked, no Stock Token market could settle.

Effect on Kasumi: settlement is all-or-nothing per market. If one participant in a market's batch is blocked, or the token is paused, the transfers revert and that market segment does not settle. Other markets in the epoch are unaffected. The operator simulates before submitting and re-matches without orders that fail its checks. When the mainnet deployment was made those checks covered nonce, balance and allowance only, not the blocklist or pause state, so a blocked party could stall its market for the epoch. The operator now reads both before matching: an order whose owner or receiver is on the blocklist is rejected as TRANSFER_BLOCKED, a paused token halts its market for the epoch (TOKEN_PAUSED), and a blocked settlement contract halts every Stock Token market (SETTLEMENT_BLOCKED). This was exercised on a fork of mainnet, not on mainnet itself. USDG exposes no registry, so a blocked USDG party still goes through the re-match and withdraw path. A state change between simulation and inclusion can still revert one segment.

The same applies to a user who revokes an allowance, moves funds, cancels their nonce onchain or names a receiver that cannot take the token, after the epoch is opened. The matcher recovers by re-matching that market without the order and amending the published result (amendMarket), so one such order no longer stops the epoch from settling. The attacker can repeat it with other orders in the same market until the settlement deadline. Each attempt costs them a transaction and an order that will not fill, and it can only hold up the market they are in. If the deadline passes first, that market does not trade and the epoch reads CANCELLED, while markets that already settled stay settled. There is no bond or penalty for this in v1.

A market's batch must fit in one transaction. The number of fills per market per epoch is therefore bounded by the block gas limit, on the order of a few hundred. Chunked settlement is not implemented.

Sequencer#

Robinhood Chain has a single sequencer with first-come ordering, and it applies compliance-based transaction filtering. It can delay or exclude Kasumi transactions. If the commitment is excluded past the decryption time, or settlement past the deadline, the epoch cancels. The sequencer cannot read sealed orders or change what the contracts accept.

The commit deadline is judged by block.timestamp, which the sequencer sets, while the drand key is released on wall-clock time. If the sequencer's clock lags, a commitment can land onchain after the key is already public. The reveal delay is the margin against this; the deploy script defaults to 12 seconds, mainnet uses 15, and clients lock orders to the first drand round at or after the decryption time. A relay that exploited the lag would still be unable to settle an order that users did not sign.

Residual risks in one place#

  1. Key release does not wait for the commitment. The trigger is a time, not an onchain event. If the relay fails to anchor the root before the decryption time, the drand round is still published. The orders of that epoch become readable, the epoch cancels, and nothing executes. Intent is revealed without a trade. An event-triggered scheme would close this gap; none is available for this chain today.

  2. drand collusion or break reveals orders early.

  3. Relay metadata. IP, timing, size and count are visible to the relay.

  4. Censorship is detectable with a receipt, not preventable in v1.

  5. Abort option. The operator can let an epoch cancel after seeing it decrypted. It cannot steal or alter fills.

  6. Allocation is audited, not enforced. The contract enforces user limits and a uniform price, not the pro-rata rule.

  7. Minimum-fill heuristic can drop constrained orders.

  8. Per-market griefing. A blocked address, a paused token, a revoked allowance, an onchain nonce cancellation or an oracle move can revert one market's settlement. The matcher can re-match and amend, but a persistent griefer can keep one market from trading in one epoch.

  9. Rounding dust. Buyers pay rounded up and sellers receive rounded down. The difference, at most one raw quote unit per fill pair, accumulates in the contract and can be swept by the owner. It is recorded onchain in dust.

  10. Everything is public after settlement, including unfilled orders of the epoch.

  11. Commitment grinding. The pro-rata leftover tie-break uses the commitment. A participant can grind the salt to win it. The prize is one raw base unit.

  12. Upgradeable Stock Tokens. Token behaviour can change after a market is listed. The balance check in settlement catches fee or rebase behaviour and reverts.

  13. Unaudited contracts on mainnet. The contracts are deployed on Robinhood Chain mainnet and no external audit has been done.

  14. Owner powers. The owner can change the relay, matcher, oracle and markets, sweep dust, reconfigure timing from two epochs ahead, and cancel unsettled epochs. It cannot move user funds or settle orders outside their signed terms.

  15. Commit liveness. In the deployed app the commit depends on a serverless instance, a polling client or the cron job being alive inside the 15-second reveal window. If none is, the epoch cancels and its orders are revealed unexecuted (risk 1).

  16. Public RPC. The live relay reads and sends through an RPC endpoint. The public one rate-limits. An outage or a block at the wrong moment causes a missed commit or a missed settlement deadline.

  17. Hot keys on the host. The relay and matcher keys are environment variables on the web host. Whoever can read them can censor, withhold commits, and choose results within the matcher's limits. They cannot move user funds outside a signed order. The owner is a single key.

  18. Gas. The relay and matcher accounts must hold ETH. If either runs dry, epochs cancel.

  19. Third parties. Vercel and Neon see request metadata and stored ciphertexts. Privy sees login identifiers. Approvals and settlements are public transactions that link a wallet to Kasumi.

  20. Legal pages are drafts. The privacy, terms, cookies and risk pages in the web app are unreviewed templates.

The live deployment#

In the hosted deployment, the relay and, by default, the matcher are one serverless application holding both keys. That is a single operator in the sense of this document: the separation between relay and matcher gives no protection against it. What stays independent is the chain. The commit window, batch membership, the per-market published hash and every user constraint are enforced by the contracts, and the terminal checks inclusion against the root it reads from the epoch manager, not the one the relay reports.

As of the deployment, one epoch has run on mainnet with a single order from an unfunded wallet: committed, rejected for insufficient funds, settled empty. No trade with real tokens has settled on mainnet.