You want to sell KAS for fiat, or buy a digital item with KAS, from someone you have never met. A Telegram escrow "guarantor" solves this — until you realize the guarantor holds your money in their personal wallet and charges 3–10% for the privilege. Kaspa Escrow is the alternative: a non-custodial on-chain contract where funds are locked in a Toccata covenant, not a human's hot wallet. This guide walks through the complete mechanics — from deal creation through funding, chat, release, refund, and dispute — so you understand exactly what the contract allows and what it does not.
The problem: trust without custody
Any P2P trade has a timing gap. The buyer sends KAS first, and the seller can vanish. The seller ships first, and the buyer can claim they never received it. Traditional escrow solves this by introducing a middleman who holds the funds — but the middleman becomes the new risk.
Kaspa Escrow removes the middleman's ability to steal. The funds live in a Toccata covenant — an on-chain script that defines exactly who can spend the output and under what conditions. The operator runs the website, the chat relay, and (when needed) the arbitrator, but the money never touches the operator's wallet. Math replaces promises.
The covenant: ten paths, no theft
The escrow contract (escrow.sil) is compiled into a Kaspa address at deal creation. It holds three public keys — buyer, seller, arbiter — and several time parameters in DAA score units. Once funds arrive at this address, only ten paths can move them:
| Path | Who signs | Where funds go | Fee |
|---|---|---|---|
release | Buyer | Seller | 0.5% (min 1.2 KAS) |
refund | Seller | Buyer | 0.5% (min 1.2 KAS) |
mutual | Buyer + Seller | Any split between them | 0.5% (min 1.2 KAS) |
dispute | Buyer | Stays in covenant (state → DISPUTED) | — |
autoRelease | No signature | Seller | 0.5% (min 1.2 KAS) |
arbitrateToBuyer | Arbiter | Buyer | 2% (min 5 KAS) |
arbitrateToSeller | Arbiter | Seller | 2% (min 5 KAS) |
arbitrateSplit | Arbiter | Split between buyer and seller | 2% (min 5 KAS) |
timeoutToBuyer | No signature | Buyer | Network fee only |
timeoutToSeller | No signature | Seller | Network fee only |
Toccata covenant — a Kaspa smart-contract primitive that locks funds into an output address derived from a SilverScript program. The program validates every spending transaction against rules embedded in the script itself. The network rejects any transaction that does not satisfy the rules. See the Kaspa wiki for protocol details.
The key invariant: every path sends funds only to the buyer, the seller, or a fixed fee address. The arbitrator cannot redirect money to themselves or a third party — the script simply does not contain such a path. Every path also enforces require(tx.inputs.length == 1), preventing multi-UTXO siphoning attacks.
A feeBudget parameter (capped at 0.1 KAS) bounds the fee output so that "slack" cannot be quietly siphoned. The mutual path is the only cooperative close that *requires* a fee output — without this, two honest parties could bypass the service fee entirely.
Step by step: the deal lifecycle
1. Creation
One party opens kaspaforge.org/escrow.html and chooses:
- Role — buyer or seller
- Template — goods, OTC/exchange, or service
- Amount — in KAS (minimum 50 KAS, no upper cap)
- Terms — free text describing the deal
- Dispute window — one of six presets: 24 h / 48 h / 72 h / 96 h / 120 h / 168 h. Each preset automatically sets an arbitrator deadline (for example, 72 h window → 168 h arbiter deadline). The UI suggests a default matched to the template (goods → 72 h, OTC → 24 h, service → 120 h). Custom values outside the presets are not possible — this prevents a "micro-window" that would deny the other side any real chance to dispute.
The browser generates three key pairs locally:
- Deal key — signs on-chain spending transactions
- Funding key (buyer only) — controls the pre-funding address
- Chat key — encrypts end-to-end deal messages (separate from the deal key; cannot move funds)
All three are written to a recovery list (plain text file) and never leave the browser. The server receives only the public keys. The creator gets an invite link and a deal.html?id=<N> bookmark.
2. Join
The second party opens the invite link and sees the terms, amount, roles, and fee schedule *before* joining. If they accept, their browser generates its own deal key and chat key, downloads its own recovery list, and posts the public keys to the server. A critical step happens client-side: the join page independently computes the escrow address from the published parameters and compares it to the address the server returned. If they do not match, the join is blocked. This prevents a compromised server from redirecting funds to a lookalike covenant.
3. Funding
The buyer sees a funding address — their *own* address, derived from their funding key — and a QR code. They send KAS to this address from any Kaspa wallet. Then they click "Lock into escrow." The browser assembles a transaction that moves the funds from the funding address into the on-chain covenant (the escrow address). A plain transfer to the escrow address does *not* create the contract — the two-step process (fund your address, then lock) ensures the covenant output has exactly the right script and parameters.
Kaspa Escrow is live on mainnet. Create a deal, try the wizard, or read the full recovery specification — everything is at kaspaforge.org/escrow.html. The contract and recovery tooling are open source at github.com/Kaspaforge/kaspaforge. If you also need a non-custodial vault for your everyday KAS, see Kaspa Safe; for encrypted deal management across devices, use Desk.
4. Active period
Once funded, both sides see the active panel. The dispute window timer counts down. During this window:
- The buyer can click Release → funds go to the seller (minus the release fee).
- The seller can click Refund → funds return to the buyer (minus the release fee).
- Both sides can use the deal chat — end-to-end encrypted messages anchored on-chain via the Kasia protocol. The server relays ciphertext; it never sees plaintext. Media (images, video) is encrypted client-side with a random key, uploaded as an opaque blob, and the decryption key travels inside the encrypted chat message. After decryption, the client verifies the SHA-256 hash against the anchor in the message.
5. Auto-release (happy path with silence)
If neither party clicks anything and the dispute window expires, the server's watcher cycle submits an autoRelease transaction. Funds go to the seller. This protects sellers from buyers who receive the goods and then disappear.
6. Dispute
If the buyer clicks Open dispute during the window, the covenant transitions from ACTIVE (mode 0) to DISPUTED (mode 1). The UTXO is recreated on-chain with a fresh age counter and the arbiterDeadline timer starts. From this point:
- Both sides submit materials to the arbitrator through the deal panel (descriptions, screenshots, tracking numbers).
- Either side can reveal their chat secret key to the arbitrator, who then decrypts the conversation transcript as evidence. The chat key is separate from the deal key — revealing it does not give the arbitrator control over funds.
- The arbitrator issues a verdict: all to buyer, all to seller, or an N% split. The verdict is non-binding — either party can reject it. If neither party accepts within 24 hours (configurable via
KSAFE_VERDICT_WINDOW_SECS), the case auto-escalates. - If the arbitrator stays silent past the deadline, the emergency timeout kicks in: funds go to the default side (usually the buyer) with no service fee at all.
At any point during a dispute, the buyer can still Release and the seller can still Refund — amicable resolution is always available.
Key management and recovery
Every deal has its own keys, generated in the browser. The recovery list is the only copy. Losing it means losing access to your side of the deal. The funds do not vanish — they will move through the normal path (release, refund, auto-release, or timeout) — but you lose the ability to initiate actions from your side.
The published recovery kit (github.com/Kaspaforge/kaspaforge/tree/main/recovery-kit) contains a pure-Rust core and a CLI tool (dealctl) that can extract, verify, fund, release, refund, dispute, and build transactions offline. It connects directly to any Kaspa v2+ node via gRPC — no hosted endpoints required. An air-gapped signing flow exists: the offline machine holds the key, the online machine prepares the transaction, and the signed result is submitted online. Four rounds of independent review have been completed with all findings closed.
Trade-offs and honest boundaries
Non-custodial ≠ trustless arbitration. The contract guarantees funds cannot be stolen. It does not guarantee a fair verdict. The fairness of a dispute outcome depends on the human arbitrator (or AI mediator) evaluating evidence. The AI arbiter's verdict is explicitly non-binding.
Off-chain fulfillment is invisible to the contract. Whether the goods actually arrived, whether the fiat payment actually cleared — the covenant cannot see this. That is precisely why a dispute path and arbitrator exist. Keep all deal communication inside the deal chat: the on-chain Kasia messages cannot be backdated or forged, making them real evidence.
Service going down ≠ losing funds. The emergency timeout path works without any server or signature. If Kaspa Forge disappears tomorrow, your funds return to the default side when the arbiter deadline expires. The recovery CLI can also force-settle any deal state against any Kaspa node.
External audit is still ahead. The contract has passed adversarial testing (52/52 VM checks, full simnet end-to-end, four independent review rounds of the recovery kit), but the formal external audit has not yet been completed. Verify the contract on-chain before committing significant amounts.
Minimum 50 KAS. Below this, the arbitration fee absorbs too large a share. There is no upper cap.
Fee enforcement. The release/refund fee (0.5%, min 1.2 KAS) and the dispute fee (2%, min 5 KAS) are enforced by the script itself — they are not optional and cannot be bypassed. The fee is shown in the panel before you confirm.
Sensitive data cleanup. When a deal closes, the server erases evidence, forensics, mutual signatures, and buyer payment details. Only the deal method and final verification status remain as anonymized statistics.
---
*The contract source (escrow.sil), recovery core, and CLI tool are published at github.com/Kaspaforge/kaspaforge. For a general overview of how Kaspa Forge builds on Toccata covenants, see the architecture index.*
FAQ
Can the escrow operator steal my funds?
No. The funds sit in an on-chain Toccata covenant — a Kaspa smart contract — not with the operator. The script allows only ten fixed spending paths, and every one of them sends funds strictly to the buyer, the seller, or a fixed fee address. Even the arbitrator's signature only opens paths to the buyer, the seller, or a split between them. Sending KAS to any other address (including the arbitrator's own wallet) is rejected by the network.
What is the minimum deal amount?
50 KAS. Below that threshold the arbitration fee (2%, minimum 5 KAS) consumes too large a share. There is no upper cap.
What happens if Kaspa Forge goes offline?
A built-in timeout returns funds to the default side — usually the buyer. The contract enforces this path without any signature or server interaction. Both parties also have a published recovery kit (open-source CLI tool) that can build and submit settlement transactions against any Kaspa node, independently of the website.
Can the seller refund after I have already received the goods?
The seller can click Refund at any time, but only because the buyer has not yet clicked Release. Once the buyer clicks Release, the funds move to the seller and the deal closes. The design assumes the buyer inspects the goods and releases promptly. If the seller refunds unfairly, the buyer can open a dispute before the window expires.
How much does it cost?
Creating a deal is free. Release or refund costs 0.5% of the amount (minimum 1.2 KAS). If a dispute is opened, arbitration costs 2% (minimum 5 KAS). The only path with no service fee is the emergency timeout. Fees are enforced by the on-chain contract and shown before you confirm.
Put your KAS where theft can be cancelled
A covenant vault on Kaspa mainnet: your keys, your rules, our tooling. Free on-chain, forever.
Create a vault
