A private STRK20 capability that triggers one approved Starknet action and returns the same value to a fresh private note.
Live demo: vocap-protocol.vercel.app · Video: YouTube Demo · Docs · Security · Submission: not linked yet
The browser frontend ships the public landing page, official Docs, Capability Trace, Terms, and Privacy routes. This is the current product flow:
private STRK20 note
|
user-controlled client builds proof and wallet call
|
user approves transaction -> privacy pool -> policy-bound Router -> approved action
|
fresh private STRK20 note
Built with: Starknet Privacy / STRK20 · Starknet Cairo · Starknet Foundry · PostgreSQL · Neon Free · GitHub Actions · Render (Sepolia)
Network: Starknet Mainnet
Status: Mainnet contracts and the proof-backed V1 lifecycle are working. The Mainnet indexer runs as a bounded, read-only scheduled projection. The frontend is deployed at vocap-protocol.vercel.app. The wallet-funded Sepolia browser write remains an explicit evidence gate.
Last verified: 2026-08-31.
Private asset systems often stop at hiding ownership. They do not give that asset a narrow, enforceable rule for what it may do next.
A generic target call can use the wrong token, amount, contract, or selector. A target can also retain the capability instead of returning it. A server relayer may improve the broadcast experience, but it moves signing authority and private material into a backend.
VOCAP keeps the holder and note flow private while making the action policy explicit and enforceable. The user approves the write from their own wallet. The backend only observes public chain results.
VOCAP lets a user apply a private STRK20 capability to one configured action. The Router checks the policy, calls the approved target, and requires the same capability amount to remain available for a fresh private return note.
V1 is deliberately narrow:
- one
RETURNlifecycle; - one policy-defined token and amount;
- one approved target and selector;
- empty target calldata for the reviewed Mainnet target;
- user-approved wallet writes;
- no signer, viewing key, or capability authority in the backend.
- The user selects a private STRK20 note and a V1 policy.
- The user-controlled client uses the pinned RC2 SDK to discover the note and build the proof context.
- The proving and discovery services provide the inputs needed for the private action. Private viewing material stays in the client process.
- The wallet asks the user to approve the final
apply_actionstransaction. - The STRK20 pool calls
VocapRouter. The Router checks the pool caller, policy, token, amount, target, selector, note, and reentrancy state before calling the approved target. - The Router requires the capability to remain available, grants the pool the return allowance, and the pool produces a fresh private note. The backend later indexes the finalized public receipt.
flowchart LR
Note["Private STRK20 note"] --> Client["User-controlled RC2 client"]
Client -->|proof context| Services["Prover and discovery"]
Services -->|proof inputs| Client
Client -->|user approval| Wallet["Starknet wallet"]
Wallet -->|apply_actions| Pool["STRK20 privacy pool"]
Pool -->|privacy_invoke| Router["VOCAP Router"]
Router -->|policy-bound call| Target["Approved target action"]
Router -->|return allowance| Pool
Pool -->|fresh private note| Return["Reusable capability"]
The STRK20 privacy flow carries the note, proof, and private succession path. That gives VOCAP a useful separation of concerns: holder state can stay private while the policy boundary remains public and checkable on Starknet.
The active client uses the official PRIVACY-0.14.3-RC.2 release at commit 9bfeb8dd35565a2915a0617dff3f649bd5bb891a. The SDK builds the proof context and apply_actions call. The privacy pool owns the note lifecycle. VOCAP adds the policy-bound target call and the return requirement.
The RC2 client suite passed 259 tests across 28 files. The live prover and discovery checks returned HTTP 200, RC2 protocol responses, and a valid proof context. Their running endpoints do not expose immutable image digests or revisions, so service-image provenance remains an explicit limitation.
The public browser frontend is live at vocap-protocol.vercel.app. The fastest judge path is:
- Open the live demo and read the official Docs.
- Open
strk20.jsonand follow any of the three Mainnet proof transactions in the next section. - Run
snforge testincontracts/to see the policy and failure-path suite. - Run
corepack pnpm testinbackend/to see the indexer and wallet-boundary tests. - Run
corepack pnpm devinfrontend/to serve the frontend locally. - Check the supervised Sepolia indexer at
/healthz. This service is testnet-only and may wake from sleep on the first request.
The complete reproducible commands are in Run locally.
The browser frontend is live at vocap-protocol.vercel.app and includes the landing, Docs, Capability Trace, Terms, and Privacy routes. The wallet-funded Sepolia write gate is still outstanding, so the public site does not claim a completed browser transaction:
| Surface | Status |
|---|---|
| Mainnet private lifecycle | Completed with seven private-pool calls and three Router executions |
| Mainnet proof record | strk20.json with three qualifying transaction hashes |
| Sepolia indexer health | vocap-sepolia-indexer.onrender.com/healthz, live check returned HTTP 200 with status: ok |
| Vercel production | vocap-protocol.vercel.app, deployed from main at commit b70b4e7 |
| Browser frontend | Full frontend source in frontend/; serve locally with corepack pnpm dev |
| Demo video | YouTube Demo |
flowchart TB
subgraph Client["User-controlled client"]
SDK["Privacy SDK<br/>PRIVACY-0.14.3-RC.2"]
Wallet["Starknet wallet<br/>signs and broadcasts"]
end
subgraph Privacy["Starknet Privacy services"]
Prover["Transaction prover"]
Discovery["Discovery service"]
Pool["STRK20 privacy pool"]
end
subgraph Mainnet["Starknet Mainnet"]
Router["VocapRouter"]
Target["VocapApprovedTarget"]
end
RPC["Starknet RPC"]
Indexer["VOCAP indexer<br/>scheduled and read-only"]
DB[("PostgreSQL / Neon Free")]
SDK -->|builds proof context| Prover
SDK -->|discovers notes| Discovery
SDK -->|validated apply_actions| Wallet
Wallet -->|user-approved transaction| Pool
Pool -->|privacy_invoke| Router
Router -->|premium_action| Target
Router -->|fresh return data| Pool
RPC -->|finalized blocks and receipts| Indexer
Indexer -->|policies, executions, cursors| DB
Wallet -.->|public transaction hash| Indexer
The write path belongs to the user-controlled client, wallet, and privacy pool. The read path belongs to the RPC, scheduled indexer, and PostgreSQL projection. The two paths meet only through public transaction and receipt data.
| Technology | How we use it | Why it matters |
|---|---|---|
Starknet Privacy SDK PRIVACY-0.14.3-RC.2 |
Builds proof context, note actions, and the final pool call | Keeps private note handling in the user-controlled client and fixes the release family used for the proof path |
| STRK20 privacy pool | Receives the proven action, calls the Router, and returns a fresh note | Owns the private asset lifecycle while the Router enforces the public action policy |
| Starknet Cairo | Implements VocapRouter and VocapApprovedTarget |
Enforces pool-only entry, exact policy binding, target success, reentrancy protection, and capability return |
| Starknet wallet | Reviews, signs, and broadcasts the final transaction | Keeps write approval with the user instead of a server signer |
| Starknet RPC | Supplies finalized blocks and receipts to the indexer | Keeps the chain receipt authoritative for the public projection |
| PostgreSQL / Neon Free | Stores policies, executions, lifecycle rows, and sync cursors | Provides a replayable projection without custody of private material |
| GitHub Actions | Runs bounded Mainnet catch-up jobs on a schedule | Supports a low-cost delayed indexer with separate migration and runtime roles |
| Render | Hosts the supervised Sepolia indexer and health endpoint | Provides a simple testnet deployment path without being used as Mainnet write infrastructure |
vocap-client |
Packages the validated Router call, wallet submission, and public projection API boundary | Gives integrating apps a small npm surface without bundling private keys, viewing keys, or the pinned privacy SDK |
| Item | Current record |
|---|---|
| Chain | SN_MAIN |
VocapRouter |
0x6048ed36607367ea5ae050c745d47006214ecf66fdbf173d01eba96ec5d780a |
VocapApprovedTarget |
0x74637f577350898c64835c88216df3030050828c723c6987a3d97d6d4eb986b |
| STRK20 privacy pool | 0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a, version 2.0 |
| Mainnet policy | Policy 1, Mainnet STRK, 1 STRK, selector premium_action, empty target calldata |
| Pool protocol fee | 6 STRK per apply_actions call, with a 450-block proof window |
| Mainnet indexer | Protected workflow, scheduled bounded catch-up, no signer |
| Mainnet indexer state | Three successful GitHub Actions runs processed through block 14044147 with zero execution failures |
| Sepolia service | vocap-sepolia-indexer.onrender.com, /healthz, testnet-only |
| Active client | PRIVACY-0.14.3-RC.2 at 9bfeb8dd35565a2915a0617dff3f649bd5bb891a |
The three qualifying Mainnet Router transactions are:
0x3e1acf0c893cb5697d48295d629e86fdddd1f8ff1fd1d307c7f2ecab8c7616f0x290d3683e674714a79676be0fc13819fc410e0b7e3abb2551529e28a52f83e00xd4be56bfd8b0402e150ced5ee7f8b9c912722f9e4e940d1cc1eda7ee2098d3
The current read-only receipt checks report SUCCEEDED and ACCEPTED_ON_L1 for all three transactions. The proof hashes and both deployed addresses are also recorded in strk20.json.
| Evidence | Result |
|---|---|
| Cairo build and contract tests | scarb build passed. snforge test passed 26 tests. |
| Backend checks | Typecheck and build passed. Vitest passed 39 tests, with 1 guarded PostgreSQL test skipped when no database URL is set. |
| PostgreSQL integration | The forced disposable-database test passed 1 migration, replay, cursor, lifecycle, and reorganization case. |
| Privacy SDK | The exact RC2 checkout built successfully and passed 259 tests across 28 files. |
| RC2 proof path | Mainnet service checks returned HTTP 200, OHTTP keys, prover spec 0.10.3-rc.2, 9 proof facts, and an apply_actions call with 18 output words. |
| Mainnet lifecycle | Seven private-pool calls succeeded. The sequence covered registration, deposit, three Router executions, private Alice-to-Bob succession, and Bob's execution. |
| Target effect | VocapApprovedTarget action count advanced from 0 to 3. |
| Replay safety | Alice's spent-note reuse was rejected before wallet submission. Exact block replays are ignored by the indexer projection. |
| Mainnet indexer | Runs 33249047016, 33249526648, and 33251549194 passed setup and restricted runtime-role checks, processed through block 14044147, and reported zero execution failures. |
| Completed sequence cost | The approved run debited 80.524484515641070364 STRK from the operator wallet. This is measured historical cost for that sequence, not a quote for future activity. |
| Testnet service | The supervised Render Sepolia deployment completed migration. A live /healthz check returned HTTP 200 with status: ok. |
| Attempt | Expected behavior | Result |
|---|---|---|
Direct call to privacy_invoke |
Reject a caller that is not the configured pool | ONLY_POOL rejection covered by Cairo tests |
| Wrong token, amount, target, selector, or note | Reject values that do not match the policy | WRONG_* and INVALID_* rejections covered by Cairo and backend tests |
| Disabled policy | Stop before any target call | POLICY_DISABLED rejection covered by Cairo tests |
| Target reverts | Revert the complete action atomically | TARGET_CALL_FAILED covered by Cairo tests |
| Target retains the capability asset | Refuse to produce a return note | RETURN_FAILED covered with and without token surplus |
| Reentrant target attempts a second action | Block the nested call | Reentrancy guard covered by Cairo tests |
| Unsolicited token surplus | Preserve the surplus without blocking a valid return | Execution succeeds and the stale surplus cannot fund the next invocation |
| Reverted or unfinalized receipt | Keep it out of the successful projection | Finalized-success filtering covered by backend tests |
| Exact block replay | Avoid duplicate policies or executions | PostgreSQL replay is idempotent |
| Block gap or reorganization | Fail closed instead of rewriting history | Cursor continuity rejection covered by backend tests |
contracts/ Cairo Router, target, and Starknet Foundry tests
backend/ TypeScript indexer, persistence, health, and wallet boundary
frontend/ Vite frontend with landing, Docs, Capability Trace, and legal routes
packages/vocap-client/ Browser-safe npm client for the wallet and public API boundary
.github/workflows/ Protected Mainnet indexer workflow
render.yaml Supervised Sepolia deployment blueprint
.env.example Public configuration shape with no secrets
strk20.json Verified Mainnet proof hashes and contract addresses
LICENSE MIT license
The local docs/ directory is intentionally ignored. It contains personal operator records and is not part of the public repository.
Use the pinned toolchain from .tool-versions:
wsl.exe -d Ubuntu
cd /mnt/c/Users/<windows-user>/Desktop/VOCAP/contracts
export PATH="$HOME/.local/bin:$HOME/.asdf/shims:$PATH"
scarb build
snforge test
The backend uses Node.js 24 and Corepack pnpm:
cd /mnt/c/Users/<windows-user>/Desktop/VOCAP/backend
corepack pnpm install --frozen-lockfile
corepack pnpm typecheck
corepack pnpm test
corepack pnpm build
The PostgreSQL integration test is guarded by default. Run it against a disposable database when needed:
VOCAP_TEST_DATABASE_URL=postgresql://... VOCAP_REQUIRE_POSTGRES=1 corepack pnpm test:postgres
Running the indexer requires a migrated PostgreSQL schema, an explicit Starknet network, a matching RPC URL, a Router address, and a start block. The backend accepts no signer configuration.
The frontend uses Node.js 24 and Corepack pnpm. Serve it; do not open index.html as a file: URL.
cd /mnt/c/Users/<windows-user>/Desktop/VOCAP/frontend
corepack pnpm install --frozen-lockfile
corepack pnpm test
corepack pnpm typecheck
corepack pnpm dev
The published browser-safe client is in packages/vocap-client/ and available on npm as vocap-client version 0.1.0. It wraps the validated Router and wallet boundary. The integrating app still supplies the verified PRIVACY-0.14.3-RC.2 SDK release, so the package cannot silently change the proof revision.
cd /mnt/c/Users/<windows-user>/Desktop/VOCAP/packages/vocap-client
npm ci
npm test
npm pack --dry-run
An integrating app can install the client with npm install vocap-client@0.1.0 starknet@10.5.0. The package README contains the browser quickstart and the public projection API examples.
- The public frontend is deployed at
vocap-protocol.vercel.app. The wallet-funded Sepolia browser write remains unverified, and no demo video or screenshot set is published yet. - V1 supports
RETURNonly. The reviewed target takes no arguments, and arbitrary target calldata is outside the current policy. - The Mainnet backend is a delayed projection. Scheduled GitHub jobs and Neon Free can pause or lag, so the chain receipt remains authoritative.
- Render is used for the supervised Sepolia service. Mainnet indexing uses GitHub Actions and Neon Free, with no wallet signer or viewing key.
- The live prover and discovery endpoints passed the RC2 protocol and proof checks but do not expose immutable image digests or revisions. Their deployed image provenance is still open.
- The local test suites and recorded Mainnet lifecycle are project evidence, not a third-party security audit.
- Run and record the remaining wallet-funded Sepolia browser flow with note selection, proof progress, approval, and receipt status.
- Publish product screenshots and the required demo video after that flow is independently verified.
- Capture the scheduled indexer's zero-block no-op and publish a non-sensitive operational result.
- Record immutable prover and discovery image references when the service operator exposes them.
- Commission an independent contract and integration review before expanding beyond the V1 policy boundary.
MIT