Zero-Knowledge Proofs
When the contract handles an encrypted transfer, it has to be convinced the update is honest without being able to read the balances or the transfer amount. The tool that solves this problem is a zero-knowledge proof. This page explains what a zero-knowledge proof is and why a contract can rely on one.
The basic idea
A zero-knowledge proof is a way for one party — the prover — to convince another party — the verifier — that a particular statement is true, without revealing anything beyond the fact that it is true.
A classical example is a Sudoku puzzle. A solver claims to have a valid solution to a published puzzle. Revealing the solution would prove the claim, but it would also reveal every digit. A zero-knowledge proof lets the solver convince a verifier that the solution is valid while keeping the solution secret. The verifier learns that the claim is true, but not the hidden solution.
The same idea applies to encrypted transfers. The prover (the sender's SDK) wants to convince the verifier (the contract) that a hidden transfer is well-formed. The values inside — balances, amount, secret key — are the prover's secret. The contract ends up certain the transfer is valid, but it does not learn the hidden balances, amount, or secret key. Public inputs and normal transaction metadata are still visible.
The three properties that matter
A proof system is useful only if it has three properties at once:
- Completeness — if the statement is true and the prover follows the protocol honestly, the verifier will accept.
- Soundness — if the statement is false, no prover (no matter how clever or malicious) can produce a proof that the verifier accepts, except with negligible probability.
- Zero-knowledge — the proof reveals nothing about the prover's secret beyond the fact that the statement is true.
Completeness is what makes the system usable. Soundness is what makes it trustworthy. Zero-knowledge is what makes it private. Drop any one and the construction stops being useful: a system without completeness rejects honest users, a system without soundness lets people cheat, and a system without zero-knowledge leaks the secrets it was supposed to hide.
Statements, witnesses, and circuits
To turn the abstract idea into something that actually runs, three concrete pieces are needed.
The statement is the public claim being proven. In an encrypted transfer, it says that the stored and submitted ciphertexts form a valid hidden transfer by a sender who knows the relevant encryption secret key.
The witness is the private data that makes the statement true. The prover knows it; the verifier never sees it. For an encrypted transfer, the witness includes the sender's secret key, the cleartext old balance, the cleartext transfer amount, and the randomness used in the new ciphertexts.
The circuit is the statement written in a form a proof system can operate on — a structured description of the computation that takes the witness as input and checks every condition the statement asserts. The prover evaluates the circuit with the private witness and public inputs to produce a proof; the verifier checks that proof against the same public inputs. If the proof verifies, every condition encoded in the circuit must have been satisfied.
How ZK Stables uses this
The encrypted-transfer example is the canonical case:
- public inputs include the stored sender balance ciphertext plus the submitted new sender balance ciphertext, recipient amount ciphertext, and compliance amount ciphertext,
- the witness includes the sender's encryption secret key behind the sender EPK, cleartext values, and randomness,
- the circuit checks old balance coverage, debit correctness, and that the recipient and compliance ciphertexts encrypt the same hidden amount,
- the contract is the verifier.
The same pattern appears when any hidden value has to be acted on without revealing it. A circuit defines what counts as a valid private operation, and a proof says that this particular instance satisfies those rules.
Correctness is not authorization
A valid proof says the encrypted update is mathematically correct. It does not, on its own, say the operation is allowed to happen.
ZK Stables keep these two concerns separate:
- the proof shows that the hidden update is well-formed,
- the controller authorization says the account is permitted to perform it.
The separation matters for custody. The controller can be any standard EVM signer — a hardware wallet, a Safe, a Fireblocks policy engine, an institutional signer — and the key that signs custody actions does not have to be the same key used to generate proofs or decrypt balances. Roles can be separated cleanly: one set of keys handles authorization and approvals, another handles the cryptographic mechanics of moving encrypted value.
What proofs do and do not hide
Zero-knowledge proofs hide the values inside the computation. They do not, by themselves, hide the surrounding metadata.
In the Encrypted Balances layer, this means amounts and balances are hidden, but the sender and recipient accounts remain visible and the transaction graph remains public. Hiding the graph as well is what the Shielded layer is for — see Privacy Model for the layered view and Shielded Layer Preview for what changes there.