For institutions · exchanges & on-ramps

Accept private funds without accepting the risk.

A ra:st withdrawal arrives with a cryptographic receipt proving it descends from an association set you trust — and avoids the blocklist. You verify it from public data, with no cooperation from the user and no privileged access.

01 · The fungibility problem

Why you reject mixer withdrawals today

▸ plain mixer

No provenance, no acceptance

An opaque mixer severs every link between deposit and withdrawal. That buys privacy — but leaves you unable to distinguish clean funds from laundered ones. To stay compliant you reject the whole pool, and honest users lose access. The privacy is real but unusable.

▸ ra:st

Privacy with a provenance proof

ra:st keeps the user unlinkable and attaches a compliance receipt: a proof the note descends from a public association set of non-illicit deposits. You accept the exit because you can verify it avoided the blocklist — without learning which deposit it was.

02 · Verification

Three public checks at deposit time

When a user funds their account from ra:st, your system runs these against public chain data. All three are constant-cost and require no user interaction.

check 01

Trusted root

Is the receipt’s rt𝒜 a root published by a curator whose policy you accept?

✓ policy is reproducible
check 02

Valid proof

Did the withdrawal proof verify against that root on-chain?

✓ ~240K gas · constant
check 03

Fresh exit

Is the nullifier recorded once — no replay, no double-spend?

✓ nf ∈ published set
compliance check · pseudocode● reads public data only
# called when a user deposits ra:st-withdrawn funds
def accept_deposit(exit_event):
    root  = exit_event.assoc_root           # rt𝒜 on the receipt
    if root not in TRUSTED_ROOTS:          # curators you accept
        return REJECT("untrusted association policy")
    if not verify_onchain(exit_event.proof):  # already checked by contract
        return REJECT("invalid proof")
    return ACCEPT                          # descends from 𝒜, blocklist-clean
03 · The receipt

What the exit event carries

Every withdrawal emits a public event. These are the only fields you need — and the only fields that exist.

FieldMeaningYou use it to
rt𝒜Association root the proof was made againstMatch against your trusted curators
nfNullifier — the one-time spend tagConfirm the exit is fresh, not replayed
πThe zero-knowledge proof (192 B)Confirm on-chain verification passed
recipientThe payout addressMatch to the incoming deposit
04 · The boundary

What you gain, and what stays private

Compliance and privacy are not traded off. You get exactly the assurance you need — and nothing that would compromise the user.

▸ you obtain
  • Proof the exit descends from 𝒜 (blocklist-clean)
  • Assurance no sanctioned or stolen deposit can exit clean
  • A public, reproducible audit trail per withdrawal
  • Constant-cost verification — no per-user review
▸ you never see
  • Which deposit the exit originated from
  • The user’s balance or history inside the pool
  • Any spending key or private witness
  • Links between separate withdrawals
~240K
gas · verify · fixed
0
user interaction needed
100%
from public data

Private for users. Auditable for you.

Integration guides, trusted-root registries, and the compliance spec are available to institutional partners.