Zcash native contracts
Contracts without contract code
Neutral by design. Enforced by signatures.
Private, oracle-settled payments on Zcash.
Two parties lock funds, pre-sign every possible payout, and an oracle's signature makes exactly one of them valid. Money comes in from the shielded pool and goes back out to it; while a contract is open, only its collateral is visible on chain, never its terms.
Where it comes from
Tadge Dryja, at MIT's Digital Currency Initiative, publishes the design: oracle contracts that look like ordinary multisig on chain, with an oracle that never learns about them.
Adaptor signatures replace the original key tweaks; the dlcspecs standardize the messages; libraries such as rust-dlc and DLC Dev Kit make them buildable.
The same oracle messages (compatible with dlcspecs oracles), on Zcash v6 transactions, with funding and payouts that go through the shielded pool.
How it works
A client has escrowed 1.5 ZEC for a job. Three transactions were signed before the money moved. The figure plays what each possible oracle answer unlocks; pick one to look at it.
Example: Milestone-based escrowThe question: “Milestone 1 delivered?” Two arbiters announce it; both must agree. Playing each case in turn; pick one to stop.
1.5 ZEC to the contractor.
locked to both arbiters' "delivered" points1.5 ZEC back to the client.
locked to both arbiters' "not delivered" pointsEach side's money back to it.
locked until block height HEach publishes a one-time nonce for the event. From it and the oracle's key, every outcome has a point anyone can compute.
Each payout carries an adaptor signature locked to its outcome's point, and a refund is locked to a height.
The funding is signed last, so nobody commits funds before holding every payout and the refund.
The oracles' signatures complete exactly one. Usually the parties skip it and close cooperatively into shielded notes.
The math
s·G = R + e·P
Before the event, anyone can compute the right side for every outcome. When the oracle signs, its signature s is the discrete logarithm of exactly one of those points, and it completes the payout both parties pre-signed to that point. The oracle publishes a statement; it never learns which contracts use it.
With two oracles, each payout is locked to the sum of their two points for that outcome. Only the sum of both signatures completes it, so one oracle alone unlocks nothing, and two that disagree unlock nothing: the refund settles it.
Why Zcash
On Bitcoin, a DLC's funding traces back to your coins and its payouts land on addresses anyone can follow. On Zcash, money enters from the shielded pool and leaves to it. The temporary 2-of-2 in between stays public, and can still link a funding and its settlement to each other, but not to the people behind them.
| Information | Public? | Detail |
|---|---|---|
| Your funding wallet and its history | no | When you fund from shielded notes or a deposit link |
| Contract terms and payouts per outcome | no | Held by the two parties; never written on chain |
| The 2-of-2 output and its amount | yes | While the contract is open. It can link the funding and settlement transactions to each other |
| The oracle's event and attestation | yes | If the oracle publishes them; nothing ties them to a contract on chain |
| Recipients of a cooperative close | no | Shielded outputs. The total leaving the 2-of-2 is visible; the split is not |
| Recipients of a pre-signed payout | yes | Transparent until each side moves its payout into the shielded pool (the kit does this by default) |
| What recipients do afterwards | no | Ordinary shielded spending |
Unified addresses and ZIP 321 links let anyone fund a contract by scanning a QR code, shielded, with a memo naming the contract.
Each contract leaves a recovery record in a memo only your seed can read, and a maker can send one taker a private quote with nothing posted publicly.
For proof-of-payment contracts, the oracle receives the incoming viewing key of an address used only for that repayment. It can read payments arriving there, and could disclose them, but cannot spend them or see anything else you own.
A cooperative close can pay every party and up to 16 payees in one shielded transaction.
What developers can build
The simplest conditional settlement: a client funds a job, arbiters rule, and a time-locked refund covers silence. Neither side holds the other's money.
Milestone payments, freelance jobs, a team paid by share on delivery.
ZEC payouts set by a real-world price: owed dollars, paid in ZEC at the attested minute, with the other side earning a premium.
Invoices in dollars, a hedged salary, protecting a ZEC balance.
Agents that negotiate a price and get paid only if the outcome they promised is attested, settled without a platform holding funds.
Built from escrow and the desk's quote and mailbox flow today.
stable_payment · hedge · payrollescrow with up to 16 payeespay_on_payment · betQuickstart
A local Zcash chain, a desk, two arbiter oracles and two funded nodes, then an escrow from offer to shielded close.
Needs Docker, Rust 1.97 and just. Builds everything, starts a regtest chain and two nodes with 5 ZEC each.
Alice invoices Bob 1.5 ZEC; Bob funds it from a deposit link (the dev wallet pays it, as a phone would); both arbiters rule "delivered".
Expected output is on the right (abbreviated). Both nodes report a cooperative close into shielded notes, with its txid and block.
@zdlc/client talks to the same nodes; @zdlc/sdk embeds one in Node.js.
$ just dev dev stack up: alice :7950, bob :7951 (5 ZEC each) $ just demo escrow offered escrow <contract id> … a QR code for Bob's deposit link … paid 1.5002 ZEC to utest1…: <txid> funded "settlement": { "height": <block>, "how": "close", "txid": "<close txid>" }
Architecture
zDLC compiles a conditional agreement into native Zcash transactions: a 2-of-2, one pre-signed payout per outcome, and a time-locked refund. The logic is settled before any money moves.
Working on Zcash
| Contract | Network | How it settled | Block | Transaction |
|---|---|---|---|---|
| ZEC/USD payment, two oracles agreeing | testnet | Pre-signed payout, unlocked by both attestations | 4,522,041 | 612ba745…5822fe |
| Hedge traded through the desk by two agents | testnet | Cooperative close to shielded addresses | 4,522,155 | cd366082…17756f |
| Refund rebuilt from the seed alone | testnet | Time-locked refund | 4,521,979 | 13caad64…25bb5a |
| Escrow funded by scanning a deposit link | regtest | Cooperative close; both nodes agree on the transaction | 233 | reproducible |
| Team escrow: 0.75, 0.45 and 0.30 ZEC to three people | regtest | Pre-signed payout to three addresses | 256 | reproducible |
| A bet with the losing side offline | regtest | The winner settled alone | 307 | reproducible |
Testnet: getrawtransaction <txid> 1 on any testnet node. Regtest: cargo test -p zdlc-kit --release --test kit -- --ignored on a local chain. Every txid is logged in docs/spikes.
Status and security
The settlement and refund paths are tested on regtest and testnet but not yet independently audited. Do not use it for real money.
They cannot take funds, and two must agree, but colluding oracles can choose which pre-agreed payout unlocks.
Today's oracles keep their keys in a sealed file, not yet in a hardware enclave.
A proof-of-payment oracle can read every payment to the repayment address it watches, including amounts and memos. That address exists for one contract and nothing else.