> ## Documentation Index
> Fetch the complete documentation index at: https://docs.atrum.fun/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> The four moving parts and what each is trusted for.

```mermaid theme={null}
flowchart TB
  subgraph client["Your device"]
    W["Wallet + prover<br/><i>secrets never leave</i>"]
  end

  subgraph chain["On-chain"]
    SP["ShieldedPool<br/><i>never learns an amount</i>"]
    ACC["ElGamalAccumulator<br/><i>ciphertext only, cannot decrypt</i>"]
    V["Vault<br/><i>holds collateral + outcome</i>"]
    EPP["EncryptedParimutuelPool<br/><i>settlement, proof-gated</i>"]
    PR["PythResolver<br/><i>outcome = computation</i>"]
  end

  subgraph off["Off-chain"]
    SEQ["Sequencer<br/><i>liveness + ordering only</i>"]
    PUB["Publisher<br/><i>holds the committee key</i>"]
  end

  W -->|"proof + ciphertext"| SP
  SP --> ACC
  SP --> V
  SEQ -->|"grafts 64 leaves"| SP
  SEQ -->|"Merkle paths"| W
  ACC -->|"encrypted total"| PUB
  PUB -->|"coarse ratio only"| EPP
  PUB -->|"totals + honesty proof"| EPP
  PR -->|"sets outcome"| V
  EPP -->|"settled totals"| SP

  style PUB stroke:#b91c1c,stroke-width:3px
  style ACC stroke:#5B21B6,stroke-width:2px
```

## On-chain

**ShieldedPool** — the entry point for every user action. Holds the commitment tree, the
nullifier set, and the proof verifiers. Never learns an amount.

**ElGamalAccumulator** — holds the running encrypted total per market, per side. It stores
ciphertext points and has no ability to decrypt anything. Adding a stake is point addition on
BabyJubJub.

**Vault** — custodies collateral and holds the outcome. Splits deposits into YES/NO positions
and pays out against the winning side.

**EncryptedParimutuelPool** — settlement. Accepts the decrypted final totals along with a
Chaum-Pedersen proof that the decryption is honest with respect to the published committee
key. This is the only path a payout ever reads.

**PythResolver** — resolves a market from signed price data at a timestamp committed before
betting opened. See [Resolution](/concepts/resolution).

## Off-chain

**Sequencer** — batches commitments into the tree and serves Merkle paths.

<Note>
  Inserting one commitment costs more gas than a user action can afford, so actions only *queue*
  a commitment and the sequencer grafts 64 at a time. Batching is a correctness requirement of
  the gas budget, not an optimisation.
</Note>

The sequencer is trusted for **liveness and ordering only**. It cannot steal, cannot insert a
leaf nobody queued (the contract checks every submitted leaf against the on-chain queue), and
cannot choose padding (fillers are derived on-chain). What it can do is stall.

**Publisher** — the only process holding the committee key, and therefore the only thing that
can turn the accumulated ciphertext into a number. It decrypts the total, computes a coarse
ratio, and publishes only that.

<Note>
  Mid-market odds are indicative. Verifying them on-chain would require the plaintext totals,
  which is exactly what the encryption exists to prevent — so **no payout ever reads them.**
  Settlement goes through a cryptographic proof instead. The odds inform; the money is proved.
</Note>

## The flow

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant U as You
  participant P as ShieldedPool
  participant S as Sequencer
  participant O as Oracle
  participant C as Committee

  U->>P: deposit(amount)
  Note right of P: amount PUBLIC<br/>must be a ladder denomination
  S->>P: flushBatch — grafts your note

  U->>S: GET /path?commitment=...
  S-->>U: Merkle path
  U->>P: betEncrypted(proof, ciphertext)
  Note right of P: amount PRIVATE<br/>side public

  O->>P: resolve — signed price at a committed time
  C->>P: publishFinalTotals + honesty proof
  Note right of P: totals become public<br/>betting is closed, so nobody can act

  U->>P: redeemPrivate(proof)
  Note right of P: pays into a NOTE<br/>no collateral moves
  U->>P: withdraw(proof)
  Note right of P: amount + recipient PUBLIC<br/>but unlinkable to the bet
```

<Steps>
  <Step title="Deposit">
    Collateral enters the Vault, a commitment is queued, and the sequencer grafts it into the
    tree.
  </Step>

  <Step title="Bet">
    A proof shows you own an unspent note without revealing which. The encrypted stake is
    added to the accumulator. A position note is queued.
  </Step>

  <Step title="Resolve">
    The oracle resolver reads a signed price at the committed timestamp and sets the outcome.
  </Step>

  <Step title="Settle">
    The committee publishes final totals with a proof that the decryption is honest.
  </Step>

  <Step title="Redeem">
    A winning position becomes a settled note. No collateral moves.
  </Step>

  <Step title="Withdraw">
    A settled note becomes public collateral, in a fixed denomination, at a time of your
    choosing.
  </Step>
</Steps>

## Uniform gas envelope

Monad charges the **declared** gas limit, and that limit is a public field on the transaction.
A snug per-action limit would reveal which private action you took even though the proof stays
sealed.

So every user action is submitted with one identical declared limit. Privacy has a measurable
price, and this is where it is paid. See [Performance](/reference/performance).
