Skip to content
@zerowage-protocol

zerowage-protocol

Zero-knowledge payroll infrastructure on Stellar. Prove payroll was disbursed correctly without revealing what anyone earns.

ZeroWage Protocol

Zero-knowledge payroll infrastructure on Stellar.
Prove payroll was disbursed correctly. Without the blockchain learning what anyone earns.


What we're building

Every crypto payroll tool today puts salaries on a public blockchain. The amounts are permanent, searchable, and visible to anyone — employees, competitors, journalists, anyone with a block explorer. Companies that care about privacy don't put payroll on-chain. Companies that put payroll on-chain lose privacy.

ZeroWage resolves this contradiction using zero-knowledge proofs. Instead of publishing salary amounts, an employer publishes a cryptographic proof that the salary math is correct. The Stellar blockchain records the proof — not the numbers that made it valid.

The result: on-chain payroll with off-chain privacy. Verifiable by anyone. Readable by no one.


How it works

Employer's browser                Stellar Blockchain
──────────────────                ──────────────────

salaries[] (private)              total: 18,500 USDC
      ↓                           recipients: 5
ZK circuit runs                   proof_verified: true
      ↓                           proof_hash: e6b361...
Groth16 proof  ──────────────▶
(384 bytes)                       ← salaries never appear here
  1. The employer enters salaries into the ZeroWage app. The data never leaves their browser.
  2. A Circom 2 circuit with 1,205 constraints proves three facts about the salary array without revealing it: the sum equals the claimed total, every salary meets the minimum threshold, and this specific batch produced this proof.
  3. The Groth16 proof is submitted to a Soroban smart contract on Stellar. The contract runs real BN254 elliptic curve pairing verification using Stellar's native host functions. If the pairing equation holds, the proof is accepted.
  4. A nullifier is stored on-chain, preventing the proof from ever being reused.
  5. USDC payments are sent to recipient wallets. Both the proof transaction and the payment transaction are recorded together.

The blockchain knows the total was disbursed and the proof is valid. It knows nothing else.


Repositories

The core protocol implementation. Everything in one monorepo:

Directory Contents
circuits/ payroll.circom — 1,205 constraints, Groth16/BN254, Poseidon commitment
contracts/ Soroban verifier in Rust — real BN254 pairing, nullifier system
app/ Next.js 16 frontend — wizard, dashboard, proof explorer, attestation

Live deployment: https://zerowage-theta.vercel.app

Contracts:

Network Address
Stellar Testnet CCOEJ6QC6ZGGA2GIY72IW3MDN6LNJHQSB2XWRZR3WSLE3PVVE6QVUYAP

Technical foundation

The ZK circuit

payroll.circom is compiled with Circom 2.2.2 and proves with Groth16 over the BN254 curve. Three constraints are enforced:

Constraint 1 — Sum correctness

running[n] === total;

The claimed total must equal the actual sum of all salary inputs.

Constraint 2 — Minimum salary floor

active_and_geq[i] <== is_active[i] * geq[i].out;
active_and_geq[i] === is_active[i];

Every active recipient's salary must meet the configured minimum. Zero-padded inactive slots are correctly exempted using LessThan components to compute is_active[i] per slot.

Constraint 3 — Poseidon batch commitment

hash.out === commitment;

Poseidon(salaries[0..8]) binds the proof permanently to this exact salary batch. A proof from a different payroll cycle cannot be replayed for this one.

Circuit stats: 1,205 non-linear constraints · 2,094 wires · 20 private inputs · 4 public inputs

The Soroban verifier

The contract performs genuine on-chain Groth16 verification using Stellar's native BN254 host functions:

let neg_a = -proof.a;
let vp1 = vec![env, neg_a,   vk.alpha, vk_x,     proof.c];
let vp2 = vec![env, proof.b, vk.beta,  vk.gamma, vk.delta];
Ok(bn.pairing_check(vp1, vp2))

This is not a structural check. The pairing equation e(-A,B)·e(α,β)·e(vk_x,γ)·e(C,δ) = 1 is evaluated on-chain. A fabricated or mutated proof fails verification and the transaction reverts.

Nullifier system

Every accepted proof's SHA-256 hash is stored in persistent contract storage. Resubmitting the same proof returns ProofAlreadyUsed. Combined with the Poseidon commitment, this makes proofs single-use and batch-specific — the same primitive used in Zcash and Tornado Cash for double-spend prevention.

Approval workflow

Before a payroll run can be submitted, a designated CFO wallet must approve it. The approval mechanism requires no backend: the CFO sends a 1 XLM payment with the run ID as a Stellar text memo to the admin's wallet. The admin's browser polls Horizon for the memo. When it appears, submission unlocks. Stellar itself is the coordination layer.


What's been built

Cryptographic core

  • Real Groth16/BN254 verification on Stellar — not a structural check
  • On-chain nullifier replay protection
  • Poseidon commitment binding each proof to its exact salary batch
  • Trusted setup using Hermez Perpetual Powers of Tau (2¹²)
  • Browser-side proof generation via snarkjs WASM (~2 seconds)

Product

  • 5-step payroll wizard: employees → review → proof → approval → submit
  • Manual entry and CSV import with wallet address validation
  • Department tagging and filtering
  • CFO approval workflow via Stellar memo payments
  • Wallet-gated approval: only the configured approver address may sign
  • Draft and approved runs persist in a dedicated pending page
  • Resume any draft run via ?runId= without restarting

Data and privacy

  • Salary data encrypted with AES-GCM (256-bit) before leaving the browser
  • Encryption key derived from the admin's Stellar wallet address via PBKDF2
  • Encrypted ciphertext stored in Supabase — unreadable by the server
  • Falls back to localStorage when Supabase is not configured

Verification and audit

  • ZK payslip PDF per employee — proof hash, contract address, privacy notice
  • Public attestation page (/verify/[txHash]) — no authentication required
  • Proof Explorer with public inputs visible, salary inputs shown as ████████
  • Receipt download in .txt and .json formats
  • Both proof tx and payment tx linked to Stellar Expert

Infrastructure

  • GitHub Actions CI: contract tests on every PR (cargo test)
  • GitHub Actions CI: Next.js build check on every PR
  • Encrypted cross-device storage via Supabase
  • Horizon SSE streaming for near-instant approval detection
  • Wallet-native auth via Freighter — no email, no password

Roadmap

Milestone Status
v0.1.0 — Hackathon release ✅ Complete
v0.2.0 — Encrypted storage + circuit fix + streaming ✅ Complete
v0.3.0 — Multi-sig approval + mainnet prep 🔄 In progress
v0.4.0 — Recursive proof aggregation (20+ recipients) 📋 Planned
v0.5.0 — SEP-24 fiat off-ramp integration 📋 Planned
v1.0.0 — Mainnet launch + auditor portal 📋 Planned

Contributing

ZeroWage is actively seeking contributors. We have 40+ open issues across four difficulty tiers:

Points Difficulty Examples
100 Trivial Documentation, good first issues, small UI fixes
150 Medium New features, frontend components, API endpoints
200 Hard Circuit changes, contract functions, integrations

Every issue includes:

  • A specific implementation plan
  • Exact files to modify
  • A screen recording requirement showing the feature working

Browse issues: https://github.com/zerowage-protocol/ZeroWage/issues

Good first issues: https://github.com/zerowage-protocol/ZeroWage/issues?q=label%3A%22good+first+issue%22

Getting started

git clone https://github.com/zerowage-protocol/ZeroWage
cd ZeroWage/app
pnpm install
cp .env.example .env.local
pnpm dev

Read CONTRIBUTING.md before opening a PR.

What we look for in PRs

  • The issue is referenced in the commit message (Closes #N)
  • A screen recording is attached showing the feature working end-to-end
  • Existing tests pass (cargo test for contract changes)
  • New tests added for new contract functions
  • No salary data appears in logs, exports, or UI elements it shouldn't

Why Stellar

Stellar is the only production blockchain where this project is currently possible. The X-Ray protocol upgrade introduced native BN254 host functions — bn254_g1_mul, bn254_g1_add, bn254_pairing_check — making Groth16 proof verification economically viable on-chain. On Ethereum, the equivalent verification costs hundreds of thousands of gas. On Stellar, it costs a fraction of a cent.

Beyond the cryptography: USDC is a first-class asset on Stellar, not a wrapped token. Settlement is 5 seconds. The Stellar Development Foundation's financial inclusion mission is directly aligned with ZeroWage's goal of making compliant, private payroll accessible to any company paying anyone, anywhere.


Community


Acknowledgements

iden3 for Circom and circomlib.
Stellar Development Foundation for Soroban and the BN254 precompiles.
Hermez Network for the Powers of Tau ceremony.
Aztec Protocol for advancing practical ZK systems.


A payroll spreadsheet has always had two columns nobody could reconcile: who gets paid, and who's allowed to know. ZeroWage doesn't pick a side. It proves the first column is correct and makes the second column irrelevant — not by promising to keep a secret, but by never knowing it in the first place.

Pinned Loading

  1. ZeroWage ZeroWage Public

    The first payroll protocol with on-chain ZK verification on Stellar where the proof is the product. ZeroWage uses Groth16 ZK proofs to let companies publicly attest to payroll correctness on Stella…

    TypeScript 8 8

Repositories

Showing 2 of 2 repositories

People

This organization has no public members. You must be a member to see who’s a part of this organization.

Top languages

Loading…

Most used topics

Loading…