A confidential, on-chain prediction-market dark pool on Solana β sealed order flow, transparent settlement.
Orders are encrypted client-side and matched privately inside an Arcium MXE
over multi-party computation β so no node, relayer, or rival trader can read an order until it fills.
Every ~1.2 seconds a Frequent Batch Auction clears in two tiers (peer-to-peer first, a hedged
market-maker backstop second), and a raw Pinocchio
#![no_std] engine settles collateral in Token-2022 β zero heap, zero-copy, atomic per batch.
No Anchor. No
solana-program. No heap. The settlement program is raw Pinocchio with native Ed25519-precompile signature verification andbytemuck::Podaccount state.
| Pillar | How ShadowState delivers it | |
|---|---|---|
| π | Confidential | Orders are sealed with x25519 + the Rescue cipher in the browser and matched on secret shares inside an Arcium MXE (Cerberus MPC). Nothing is revealed but the cleared aggregate β front-running has no surface to attack. |
| π | Decentralized | Matching runs across independent Arcium nodes, not a trusted operator; settlement is a permissionless on-chain program. Trust is cryptographic, anchored by the cluster's callback attestation. |
| β‘ | Scalable | Users write to isolated ingestion PDAs, never one contended order book, so Sealevel stays parallel; matching is amortized off-chain and the whole batch settles in one transaction. |
| βοΈ | On-chain settlement | A no_std, zero-copy Pinocchio engine verifies the batch, runs deterministic two-tier clearing, and moves collateral via Token-2022 β deterministic, auditable, atomic. |
Both on-chain programs are deployed and executable on Solana devnet today:
| Program | Role | Framework | Program ID |
|---|---|---|---|
Settlement engine (program/) |
Holds collateral, writes positions, pays out | Pinocchio (no-Anchor) | FP8riDGv8jrif5G8QfprfzPeNR8kQ3UUrpTp6EXByDVZ |
Arcium MXE gateway (shadowstate_mxe/) |
Sealed-order ingestion + confidential clearing | Anchor (isolated glue) | E3GFUytcsMFgYgwTrHoob1YvhB4UvqTzj4bFWzE5dNXe |
The full settlement product (create market β mint test-USDC β deposit β resolve β claim) works on
devnet now via the web/ dApp. The end-to-end confidential-matching loop needs the one-time
on-chain circuit upload + relayer service β gated only on a non-rate-limited RPC (see
DEPLOYMENT.md).
A natural objection: if a market-maker (MM) backstops every unmatched order, doesn't it just
accumulate risk and lose? No. The MM is fully collateralized on-chain, and the moment it absorbs a
residual position, the mm-gateway delta-hedges that exposure onto external venues (Polymarket,
Kalshi) to net it toward zero. The MM earns the spread, not a directional bet β which is what makes
a brand-new confidential venue liquid from day one.
| Layer | Status | Notes |
|---|---|---|
program/ β on-chain settlement engine |
β Live on devnet | Compiles to SBF; settlement, full collateralization, resolution + winner payout, all tested against the real Token-2022 + Ed25519 precompile. |
protocol/ β frozen wire contract |
β Real | The immutable byte interface shared by every crate, with compile-time size asserts. |
shadowstate_mxe/ β Arcium project (circuits + gateway) |
π’ Built + deployed to devnet | Genuine confidential computation β encrypted-ixs/: init_book / ingest_order / clear_batch β plus the Anchor MXE gateway. Compiled by arcium build; gateway live at E3GFβ¦dNXe. |
mpc-core/ β relayer + MPC model |
Re-derives per-user fills from the gateway's BatchCleared and builds the exact protocol frame the on-chain program accepts byte-for-byte. The single-process model mirrors the MPC primitives; the live decentralized run is the next wiring step. |
|
mm-gateway/ β MM hedging relayer |
Hedge / risk / portal math is fully tested; the WS/HTTP/RPC venue adapters are real code, not yet run against live Arcium / Polymarket / an RPC node. |
Everything builds; 108 tests pass; zero compiler/clippy warnings. The code is correct and internally consistent end-to-end. Both contracts are deployed on devnet; the remaining work is operational wiring (circuit upload β relayer loop β live venue adapters), not new protocol design.
Resolution & full collateralization are implemented. Every contract is backed by
$1in the vault (Tier-1 YES/NO pairs + the MM backstop viaDepositMmCollateral);ResolveMarketsets the outcome andClaimWinnings/ClaimMmWinningsredeem winners at$1/contract. A trusted resolver authority sets the outcome today β the hook for an optimistic oracle.
ShadowState is a three-layer system. Each layer has one job, and the boundaries are where the trust model changes β confidential β deterministic β on-chain.
| # | Layer | Crate / where | Responsibility | Trust anchor |
|---|---|---|---|---|
| 1 | Confidential circuit layer (Arcium MXE) | shadowstate_mxe/encrypted-ixs/ β 3 Arcis circuits |
Encrypts orders, matches them over MPC secret shares inside the Arcium MXE, reveals only the cleared aggregate. init_book opens the encrypted book Β· ingest_order folds in a sealed order Β· clear_batch runs the auction. |
Cerberus MPC β no single node sees an order |
| 2 | Coordination / relayer layer | mpc-core/ (+ mm-gateway/) |
Listens for BatchCleared, re-derives per-user fills deterministically (two-tier), builds the protocol frame, and submits it. mm-gateway delta-hedges the MM's residual onto external venues. |
Deterministic & verifiable against the revealed clearing |
| 3 | On-chain settlement layer (Pinocchio) | program/ |
Verifies the batch authority, runs Tier-1 P2P + Tier-2 MM clearing, mutates the zero-copy position ledger, moves Token-2022 collateral β atomically per batch. | Solana consensus + the gateway/committee attestation |
The Arcium circuit layer (Layer 1) is where the privacy lives β it is the confidential matching engine, distinct from the on-chain settlement program. Orders only ever exist in the clear after Layer 1 hands a result down.
ββββββββββββββββββββββββββββ off-chain ββββββββββββββββββββββββββββ
client β Arcium MXE (3 Arcis circuits) mm-gateway β
seals βββββββΆ β’ init_book β open encrypted book β’ WS event ingest β
order β β’ ingest_order β fold sealed order β’ delta-hedge engine β
(x25519 + β β’ clear_batch β MPC match on shares β’ cross-venue orders β
Rescue) β β reveals ONLY the aggregate β’ risk retune portal β
β β BatchCleared event β β
ββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββΌβββββββββββ
mpc-core relayer: re-derive fills UpdateRiskParams tx
β deterministic two-tier frame β
β SubmitBatchTrusted β
ββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββΌβββββββββββ
on-chain β program/ (Pinocchio, no_std, zero-copy) β
β β’ verify committee/gateway authority over the batch β
β β’ Tier-1 P2P cross @ $0.50 β’ Tier-2 PropAMM residual pricing β
β β’ mutate Pod position ledger β’ Token-2022 TransferChecked β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Two-tier clearing. Tier-1 crosses overlapping YES/NO demand at the $0.50 midpoint with zero MM
impact. Tier-2 prices the one-sided residual the MM backstops via a PropAMM skew premium, clamped
to [$0.01, $0.99]; that premium is the MM's spread fee.
Confidentiality model. Privacy lives in the off-chain MPC layer β the only place encrypted orders exist. On-chain settlement is deterministic plaintext: a zero-copy position ledger + plaintext Token-2022 transfers. The hidden surface is the order book during the auction (which is what defeats front-running); final positions are public β confidential order flow, public settlement.
Scenario: Alice buys YES 100, Bob buys NO 100 β they cross peer-to-peer at $0.50 (no MM needed) β then the market resolves YES and Alice claims. Two on-chain programs are involved:
- GW = the Anchor MXE gateway (
shadowstate_mxe, devnetE3GFβ¦dNXe) - ST = the Pinocchio settlement engine (
program/, devnetFP8riβ¦ByDVZ)
PDAs: MarketState=[b"market",authority] Β· Committee=[b"committee",market] Β·
VaultAuthority=[b"vault",market] Β· UserPosition=[b"pos",market,owner] (per user) Β·
BatchBook=[b"book",market,epoch]. The Vault and MM account are Token-2022 accounts; the vault's
token authority is the VaultAuthority PDA.
| # | Ix (prog) | Signer | Accounts touched | Effect |
|---|---|---|---|---|
| 0a | InitializeMarket (ST) |
authority | payer, authority, mint, Vault, MM acct, MarketState(w), Committee(w), system | creates market + committee + binds vault/mint |
| 0b | DepositMmCollateral (ST) |
MM | MM, MarketState(w), MM-token(w), Vault(w), mint, token-prog | TransferChecked MMβVault; credits mm_collateral |
| 0c | init_*_comp_def Γ3 + upload (GW) |
deployer | MXE, comp-def, LUT, arcium-prog, system | registers init_book / ingest_order / clear_batch circuits |
| # | Ix (prog) | Signer | Accounts touched | Effect |
|---|---|---|---|---|
| 1 | InitUserPosition (ST) |
Alice | payer, Alice, MarketState, UserPosition(Alice)(w), system | creates Alice's position PDA |
| 2 | DepositCollateral (ST) |
Alice | Alice, MarketState, UserPosition(Alice)(w), Alice-token(w), Vault(w), mint, token-prog | TransferChecked AliceβVault; credits collateral |
| 3 | (repeat 1β2 for Bob) | Bob | β¦ UserPosition(Bob), Vault β¦ | Bob funded |
| 4 | init_book (GW) |
relayer | queue acctsΒΉ + BatchBook(w, init) | opens an encrypted empty book for (market, epoch) |
| 5 | ingest_order (GW) |
AliceΒ² | queue acctsΒΉ + BatchBook(w) | Alice's sealed YES-100 folded into the encrypted book β side/size hidden |
| 6 | ingest_order (GW) |
BobΒ² | queue acctsΒΉ + BatchBook(w) | Bob's sealed NO-100 folded in |
ΒΉ queue accts = payer, sign_pda, MXE, mempool, exec_pool, computation, comp_def, cluster, fee_pool, clock, system, arcium_program.
Β² each order is sealed with the client's own x25519 key to the MXE pubkey; the tx can be sent by the user or a relayer.
| # | Ix (prog) | Signer | Accounts touched | Effect |
|---|---|---|---|---|
| 7 | clear_batch (GW) |
relayer | queue acctsΒΉ + BatchBook | Arcium ARX nodes run the MPC match over secret shares β emit BatchCleared (total_yes=100, total_no=100, matched=100, net=0) β only the cleared result is revealed |
| # | Ix (prog) | Signer | Accounts touched | Effect |
|---|---|---|---|---|
| 8 | SubmitBatchTrusted (ST) |
settlement-authority (relayer) | settlement-authority, MarketState(w), UserPosition(Alice)(w), UserPosition(Bob)(w) | relayer (mpc-core) re-derives per-user fills from BatchCleared, builds the protocol frame, submits β ledger: Alice.yes_qty=100, Bob.no_qty=100, collateral debited $0.50 each, last_epoch++ |
(Committee path instead: SubmitBatch adds the Committee + Instructions sysvar + Ed25519 precompile ixs.)
| # | Ix (prog) | Signer | Accounts touched | Effect |
|---|---|---|---|---|
| 9 | CloseMarket (ST) |
authority | authority, MarketState(w) | trading β CLOSED (no more settlement) |
| 10 | ResolveMarket (ST) |
resolver | resolver, MarketState(w) | sets outcome = YES_WON |
| 11 | ClaimWinnings (ST) |
Alice | Alice, MarketState, UserPosition(Alice)(w), Alice-token(w), Vault(w), mint, VaultAuthority, token-prog | TransferChecked VaultβAlice = yes_qty Γ $1 = 100; zeroes the position. (Bob's losing claim β NothingToClaim.) |
Net: orders never appear in the clear until step 7; everything Solana sees before that is an
encrypted BatchBook. Money only moves at deposit (2/3), the MM backstop reservation (internal at 8),
and payout (11) β all TransferChecked against the same Vault.
Arcium is a decentralized confidential-computing network on Solana. MXEs (Multi-party eXecution Environments) run a compiled Arcis circuit across independent nodes that compute over cryptographic secret shares, then post an encrypted result + an on-chain callback.
The real Arcium SDK is Anchor-coupled, which conflicts with this project's No-Anchor law. The
resolution (see ARCIUM_INTEGRATION.md) is a two-program split: a thin
Anchor gateway (shadowstate_mxe/) owns only the Arcium plumbing, while the value-bearing
Pinocchio settlement engine stays Anchor-free. To run the full confidential loop you need:
- The compiled Arcis circuits uploaded on-chain to the MXE (one-time;
init_book/ingest_order/clear_batch). - A cluster (devnet offset
456) + its x25519 pubkey (clients seal to it). - A funded Solana payer (computations are metered).
- The relayer service β the ~1.2 s
clear_batchβSubmitBatchTrustedloop.
No secret credentials are hard-coded or required to build and test this repo β standard Arcium onboarding, not a ShadowState-specific secret.
# On-chain program β SBF artifact (edition 2024 needs the v1.52 toolchain)
cargo build-sbf --manifest-path program/Cargo.toml --tools-version v1.52
# Workspace (protocol + program) β runs the LiteSVM settlement suite
cargo test
# Off-chain crates are excluded from the workspace; build/test standalone
cargo test --manifest-path mpc-core/Cargo.toml
cargo test --manifest-path mm-gateway/Cargo.tomlThe off-chain crates are intentionally excluded from the workspace members so the on-chain
program's pinned dependency lock (litesvm / agave) stays untouched. They share the frozen protocol/
crate by path, so the cross-crate interface cannot drift.
| Crate | Tests | Build target |
|---|---|---|
protocol/ |
2 | workspace member |
program/ |
33 | workspace member + SBF |
mpc-core/ |
42 | standalone |
mm-gateway/ |
31 | standalone |
| Total | 108 | 0 warnings |
protocol/ Frozen wire contract: BatchHeader/UserFill, constants, discriminators, PDA seeds.
program/ On-chain Pinocchio settlement engine (state, math, sig, instructions) + LiteSVM tests.
mpc-core/ Off-chain relayer (BatchCleared β settlement) + the local MPC model/tests.
mm-gateway/ MM relayer: event ingest, delta-hedge, cross-venue dispatch, UpdateRiskParams portal.
shadowstate_mxe/ The real Arcium project β encrypted-ixs/ (Arcis circuits) + the Anchor MXE gateway.
Built by `arcium build`; gateway deployed + MXE-active on devnet.
client/ TypeScript client: seal an order (RescueCipher) β gateway ingest_order.
web/ Next.js dApp: create market, mint test-USDC, deposit, sealed order, resolve, claim.
See ARCIUM_INTEGRATION.md for the live-deployment plan and the
Anchor-vs-Pinocchio decision that "real Arcium" forces, DEPLOYMENT.md for the
devnet runbook, and ROADMAP.md for the path to a production dark pool.
- Rust 2024 edition, workspace resolver 3.
- On-chain: Pinocchio
#![no_std],no_allocator!, zero-copy#[repr(C)]+bytemuck::Pod, no Borsh on hotspots, explicitResult<_, ShadowError>β nounwrap/expect/panic!in settlement paths. - No Anchor, no
solana-program, no typosquatted or license-incompatible dependencies in the value-bearing path (Anchor is isolated to the one MXE-glue gateway). - Frozen cross-crate byte contract in
protocol/with compile-time size asserts.
MIT.