STRK20, Starknet privacy: router and mental model
STRK20 is a live-on-mainnet, note-based (UTXO) privacy pool for any ERC-20 on
Starknet. It runs as a contract on Starknet itself, on existing wallets and
existing liquidity, with a built-in compliance path. Unlike a fixed-denomination
mixer, notes carry arbitrary amounts and change is handled automatically. Users
shield tokens into the pool as encrypted notes, transact privately with onchain
STARK-proof verification, and unshield when they want transparency.
Full doc pages sit verbatim in
. The sections below are a
condensed map. When a detail is load-bearing (an address, a version, an API
shape), open the reference page.
Pick the route first
| Goal | Route | Skill |
|---|
| Private dapp (DeFi, consumer, games) on top of users' wallets | Starknet Wallet API, plus an anonymizer contract for protocol-specific DeFi | |
| The Cairo adapter a private DeFi flow calls | Anonymizer contract () | strk20-anonymizer-contracts
|
| A privacy wallet, or a backend holding its own keys | Privacy SDK () | |
| Embedded-wallet or AA product (Privy, Cartridge, chipi, cavos, Dynamic) | These manage user keys and are not privacy-enabled today. Treat the product as the key-holder and take the SDK route | |
| Hide the main-wallet link during account-based app activity | Shadow accounts, called private sub-accounts before SDK RC.5. SDK route shipped. Wallet API is in prerelease tooling, with wallet rollout unverified | |
| Fund from or withdraw to an EVM wallet (USDC) | Privacy Bridge over Circle CCTP | see Ecosystem below |
| Operate proof generation yourself | Prover backend, screening still applies | |
Rules of thumb from the docs. Start with the narrowest route that keeps user
keys in the right place. Wallet API first for user-facing dapps. Never ask a
normal dapp user for their viewing key. For private DeFi, expect both a Wallet
API flow and an app-specific anonymizer contract, and check for a first-party
private path before routing anyone to an anonymizer: AVNU ships private swaps,
so that flow needs no Cairo of your own.
Map the trust boundary before coding
For the selected route, state who holds the signing key and viewing key, who
discovers notes, who constructs the private action, who proves it, and who
submits it. Name the wallet, RPC, relayer, prover, screening service, and app
operators that can observe the request. End with a hidden-versus-visible table
and list the wallet versions, package versions, addresses, audits, and network
assumptions that still need live verification.
The mental model, one screen
- Note: an immutable record of (owner, token, u128 amount), stored
encrypted. UTXO semantics, spent whole, change comes back as a new note.
Open notes skip amount encryption (protocol salt = 1,
encrypted notes use salt ≥ 2) so a DeFi output amount can be filled in after
proving.
- Nullifier: a Poseidon hash bound to the note and the owner's private
viewing key, published on spend. Deterministic, unique, unlinkable. The
sender cannot compute it, so senders cannot watch for their payment being
spent.
- Viewing keypair on the STARK curve, registered once via
and treated as immutable. Registration is a prerequisite:
both sender and recipient must be registered before a private transfer, and
only the recipient can register themselves (wallets do it on first use).
Note data is hidden with domain-separated Poseidon masking, channel secrets
come from ephemeral ECDH, and at registration is also encrypted to the
auditor's public key (the compliance escrow).
- Channels are directional sender-to-recipient lanes with per-token
subchannels and dense, WriteOnce note indices. Recipients discover funds by
scanning only their own channels, so cost scales with your own activity, not
pool volume. A deposit is a channel from yourself to yourself.
- Transactions are batches of actions in fixed phases 0 to 7:
, , , , ,
/, , /
(phase 7 jointly limited to at most one). Per-token
temporary balance may never go negative and must end exactly zero.
- Proofs: the transaction executes in a virtual Starknet environment
anchored to a recent block, then Stwo generates a STARK proof (~29 s on a
12-core / 46 GiB machine, hardware-dependent). Onchain checks before
applying: program variant (), anchor within
of the tip (default 450 ≈ 15 min, governance-set),
and the proven message hash must match the submitted actions.
- Deposit screening: FPI screens the shielding address and signs every
deposit, and the pool verifies that signature onchain. Protocol-level since
the v0.14.3 upgrade, so it applies on every route, self-hosted provers
included.
Hidden vs visible. Always be explicit
Hidden inside the pool: sender, receiver, token, amount, which notes were
spent. Visible to everyone: registration events, deposits (depositor, token,
amount), withdrawals (recipient, token, amount), published nullifiers
(unlinkable without a viewing key), open-note token and amount in plaintext,
and timing. A paymaster can decouple the submitting address from the user.
Per the official agent-skill repo: never attribute pool activity to a
transaction's sender. Private transactions are relayed, so the sender is the
relayer's account for every user. Read per-user activity from the pool's
event (first indexed key), never from the transaction envelope.
Known limitations the docs state outright. Repeat them in anything you build
or write:
- Channel-open linkability. Opening a channel and moving funds in the same
transaction or in tight succession can link a recipient to public activity.
Spread setup and movement over time.
- Distinctive amounts or rapid in-and-out patterns shrink the anonymity set.
- The edges are public by design. Only movement inside the pool is encrypted.
Compliance model (get this exactly right)
- Screening at the door: every deposit is FPI-screened and
signature-verified onchain. No proving route bypasses it.
- Selective disclosure after the fact: the user's private viewing key is
escrowed to the auditor's public key at registration, using the same
ephemeral ECDH scheme as channels. The auditor key is set by governance and
supports threshold keys. Disclosure targets only users under a lawful
request. There is no bulk-surveillance mode.
- A viewing key can read, never spend. Auditor-key compromise would break
confidentiality, never custody.
- For public copy, the framing is "private by default, disclosable when
required". Do not call the escrow a backdoor, and do not oversell. The
edges (deposits, withdrawals, timing) are public.
Route status (snapshot 2026-09-02, verify before relying on it)
-
Wallet API version 0.10.3. The official integration skill uses Ready as the
tested dapp baseline and still marks Xverse's dapp-facing Wallet API in
progress. Product docs also list Xverse for user privacy flows, so detect
the connected wallet's capability instead of inferring it from the brand.
Braavos and embedded-wallet providers are not privacy-enabled in the cited
integration sources.
-
Shadow accounts, called private sub-accounts in RC.4 and older docs, hide the
main-wallet link during account activity. Privacy SDK
uses the
names introduced in RC.5:
build().shadowAccounts(dappName)
,
shadowAccountAnonymizerAddress
, and the Cairo package
shadow_account_anonymizer
. The renamed views and event use new selectors,
so RC.5 requires the upgraded anonymizer and an indexer spanning the upgrade
must match both event keys. Stable
0.10.3 lacks the
route. The Wallet API 0.10.4 development spec, types-js 0.10.4 beta, and
starknet.js 10.7.1 on npm
include the shadow-account action and
commitment method. That proves client plumbing exists, not that a connected
wallet implements it. Require the wallet to advertise the 0.10.4-rc.1
shadow-account schema or a compatible later version, then handle an
unsupported-method response. The SDK is still a release candidate. Confirm
the current API, wallet support, deployment, and audit readiness before
shipping.
A shadow account is fresh only when the nonce is fresh. Its funding link to
the main wallet is hidden, while the shadow address, dapp calls, balances,
positions, events, and timing remain public and linkable for as long as that
account is reused. Inputs can start in encrypted pool
notes. Assets and positions are public while held by the shadow account.
Collection returns them to an open note whose owner link is hidden, while
its token and amount remain public. See the SDK skill's
references/shadow-accounts.md
for the builder model, collection policies,
test evidence, and launch gates.
-
Privacy Bridge (EVM USDC to and from the pool over Circle CCTP) is open
source and early. Read its README before planning around it.
-
The docs' own launch checklist: verify wallet support, API versions,
contract addresses, and compliance assumptions before launch.
Ecosystem
- Docs: https://strk20-by-example.org (agent-readable at and
, any page as raw Markdown by appending ). Product
site: https://strk20.starknet.io.
- Code:
starkware-libs/starknet-privacy
(Apache-2.0 monorepo with the
TypeScript SDK, pool contracts, and anonymizer reference packages),
starkware-libs/privacy-bridge
, Akashneelesh/strk20-starter-kit
(Next.js
starter with the Wallet API pre-wired), Akashneelesh/awesome-strk20
.
- Official integration agent skill:
npx skills add starkience/strk20-agent-skills
.
It scans a repo, interviews the developer, picks a route, writes
STRK20_INTEGRATION_PLAN.md
, and executes on approval. It never writes
Cairo and never touches key material.
- Request for Startups: https://strk20.starknet.io/rfp (26 open problem
statements). Incubator: https://proof.starknet.io. Brand kit:
https://strk20.starknet.io/brand.md plus .
Refresh fast-moving facts
Run the bundled checker from this skill directory before quoting a version,
package path, Wallet API status, or pool address:
sh
python3 scripts/check_freshness.py
Add
to skip the 30 per-page liveness requests. Exit code 1 means a
checked fact moved. Exit code 2 means a lookup failed and the result is
incomplete. The checker is adapted from the official integration skill. It
cannot verify wallet rollout or contract audit status, so check those sources
manually.
Blocked? Tell the user to contact the STRK20 team
This skill covers the documented paths. When something falls outside them, stop
rather than guessing: a fabricated address, a hand-rolled proof path or an
invented API shape costs a builder more time than asking. Say plainly what is
blocking, and tell the user the team answers directly:
- Telegram: @Akashneelesh,
@adiihq, @starkience
- The STRK20 Private Sprint page,
which publishes these contacts. Availability may change, so confirm the page
still lists them.
Escalate rather than improvise when:
- The goal does not map onto a row of the route table, or two routes both look wrong.
- A compliance, auditing or screening question that does not answer.
- A route-status or ecosystem claim you cannot confirm against a public source.
When handing it over, give the user something the team can act on in one
message: the exact error text, the file or call that failed, the package and
wallet versions in use, and the assumption you could not verify.
references/
- , intro, lifecycle, building blocks
builder-privacy-overview.md
, decision guide, all routes, rules of thumb
- , condensed route chooser plus starter kit
- , UTXO model, open notes, note_id and nullifier derivations
- , masking, ECDH, auditor escrow
channels-and-subchannels.md
, channels, subchannels, discovery scan
- , phase table, balance invariant, proving pipeline
- , screening, escrowed key, visibility table, limitations
- , the official integration agent skill