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 references/. 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; choose an invoke helper or shadow account by state lifetime | strk20-wallet-api |
| The Cairo adapter a private DeFi flow calls | Anonymizer contract (privacy_invoke) |
strk20-anonymizer-contracts |
| A privacy wallet, or a backend holding its own keys | Privacy SDK (createPrivateTransfers) |
strk20-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 | strk20-privacy-sdk |
| Hide the main-wallet link during persistent account-based app activity | Stable Wallet API shadow accounts for dapps; Privacy SDK for key-holding wallets and backends | strk20-wallet-api or strk20-privacy-sdk |
| Fund from or withdraw to an EVM wallet (USDC) | Privacy Bridge over Circle CCTP | see Ecosystem below |
| Operate proof generation yourself | Local Docker prover or remote host over SSH; screening still applies | strk20-local-prover for deployment, strk20-privacy-sdk for wallet wiring |
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, use an app-specific invoke helper for stateless atomic operations and the canonical shadow-account infrastructure for persistent positions or returning pseudonymous identities. Check for a first-party path before writing Cairo: AVNU ships private swaps.
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
OPEN_NOTE_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
K = k·Gon the STARK curve, registered once viaSetViewingKeyand 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 registrationkis 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:
SetViewingKey,OpenChannel,OpenSubchannel,Deposit,UseNote,CreateEncNote/CreateOpenNote,Withdraw,InvokeExternal/ComputeAndInvoke(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 (
VIRTUAL_SNOS), anchor withinproof_validity_blocksof 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
Deposit 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-29, verify before relying on it)
-
Stable Wallet API 0.10.4 and starknet.js 10.8.0 include shadow accounts. Starknet.js documents Ready and Xverse as STRK20-capable. Detect the connected wallet's advertised capability instead of inferring support from the brand.
-
Shadow accounts, called private sub-accounts in RC.4 and older docs, hide the main-wallet link during account activity. Privacy SDK
0.14.3-rc.8uses the names introduced in RC.5:build().shadowAccounts(dappName),shadowAccountAnonymizerAddress, and the Cairo packageshadow_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@starknet-io/types-js0.10.4 and starknet.js 10.8.0 include the action and commitment method. Require the wallet to advertise Wallet API 0.10.4 or later, then handle an unsupported-method response. The low-level SDK remains a release candidate; its release status does not make the stable Wallet API route prerelease.The canonical
ShadowAccountAnonymizeris deployed at0x04f33230dc57855c6e7eabe66dfa0fde82c5458fd0e54827cdb7cb4c474888a7on Mainnet and0x010a2285310c107c731d997afc147afb7495daff6397c2d242133d9fe8d9b147on Sepolia. Re-check the current contract-address page 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
(dappName, nonce)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. Read the Wallet API skill'sreferences/starknet-wallet-api__shadow-accounts.mdor the SDK skill'sreferences/shadow-accounts.mdfor the selected integration route. -
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
/llms.txtand/llms-full.txt, any page as raw Markdown by appending.md). 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. - Agent skills:
npx skills add welttowelt/strk20-skills. They provide this router plus route-specific Wallet API, Cairo helper, SDK, and prover guidance. - 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
/brand/tokens.json.
Refresh fast-moving facts
Run the bundled checker from this skill directory before quoting a version, package path, Wallet API status, or pool address:
python3 scripts/check_freshness.py
Add --quick to skip the 32 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
references/compliance.mddoes 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/
what-is-strk20.md, intro, lifecycle, building blocksbuilder-privacy-overview.md, decision guide, all routes, rules of thumboverview.md, condensed route chooser plus starter kitnotes-and-nullifiers.md, UTXO model, open notes, note_id and nullifier derivationsviewing-keys.md, masking, ECDH, auditor escrowchannels-and-subchannels.md, channels, subchannels, discovery scanactions-and-proofs.md, phase table, balance invariant, proving pipelinecompliance.md, screening, escrowed key, visibility table, limitationsagent-skill.md, the official integration agent skillcontract-addresses.md, current Mainnet and Sepolia pool and anonymizer deployments