Kaspa Forge
Deep dive

How Kaspa Covenants Work: Programmable Spending Rules on PoW

11 Jul 2026 By OfficeForge's AI team · human-reviewed 14 min read
How Kaspa Covenants Work: Programmable Rules on PoW

A standard Kaspa transaction locks funds behind a public key: whoever holds the matching private key can spend the coins. That model works for a basic wallet — but it cannot express a rule like "this withdrawal must wait 24 hours" or "if I don't check in for six months, send the funds to my heir." Before Toccata, the only way to enforce such logic was to hand your keys to a custodial service.

Covenants change this. A covenant is a spending condition attached to a UTXO that constrains not just *who* can sign a transaction, but *how* that transaction's outputs are structured and *when* spending is allowed. On Kaspa, the Toccata upgrade brought this capability to mainnet, enabling on-chain scripts that enforce multi-path state machines — no intermediary, no multisig custodian, no trust in a third party.

This article walks through how Kaspa covenants work mechanically, and how Kaspa Safe and Kaspa Escrow build production systems on top of them.

What problem covenants solve

Consider a common self-custody dilemma. You hold KAS in a standard wallet. If your hot key is compromised, the attacker gets instant access — there is no delay, no second factor, no cancellation window. You could use a hardware wallet, but the funds are still spendable in a single transaction once the key signs.

Now imagine a different design: the funds live in an on-chain script that says, "to spend these coins, you must first announce your intention, then wait N blocks, then complete the withdrawal — and during that waiting period, a separate alarm key can cancel the transaction." That is a covenant. The rules are enforced by every Kaspa node validating the blockDAG, not by a server you have to trust.

The same mechanism generalizes. A P2P deal can lock buyer and seller funds into a contract where release requires the buyer's signature, refund requires the seller's, and a dispute path routes to an arbiter — but the arbiter can only send funds to buyer or seller, never to themselves. The contract enforces the invariant at the consensus level.

Definition

Covenant — a UTXO whose script constrains the *structure of the spending transaction* (outputs, amounts, destinations), not just the authorization (signature). On Kaspa, covenants are written in Silverscript and compiled to bytecode that nodes execute during validation.

Anatomy of a Kaspa covenant

The script language: Silverscript

Kaspa covenants are written in Silverscript (^0.1.0), a language purpose-built for Kaspa's scripting VM. A Silverscript file (.sil) defines three things:

1. Parameters — public keys, delay values, addresses, and flags set once at covenant creation time. For a vault these include the hot key, alarm key, delay duration, heir pubkey, and inheritance settings. 2. State — a compact struct stored inside the UTXO itself. When a spending transaction satisfies a covenant path, the new UTXO carries the updated state forward. 3. Entry points (spending paths) — each path specifies which signatures are required, what state transition occurs, and where the outputs must go.

The compiler produces bytecode that the Kaspa node validates against. Once funds are sent to a covenant address, the script and its parameters are immutable.

State machines on-chain

A covenant is a finite state machine living inside a UTXO. Each spending transaction must satisfy three checks:

  • Authorization — does the transaction provide the required signatures, or meet a keyless condition (e.g., the UTXO has aged past a timeout)?
  • State transition — is the current state valid for this path? You cannot complete a withdrawal if the vault is still in VAULT mode; you must initiate first.
  • Output constraints — do the transaction outputs match what the path demands? A complete path can only send funds to the destination address locked into the state during initiate.

If all three pass, the UTXO is consumed. If the path specifies it, a new covenant UTXO is created carrying the updated state. This is how the state machine advances with each transaction.

DAA-based timing

Kaspa's high block rate (10 blocks per second) and its DAA (Difficulty Adjustment Algorithm) provide a reliable, manipulation-resistant clock for covenant timeouts. Delays are measured in DAA score increments, not wall-clock timestamps. The DAA window spans 2,641 blocks, smoothing out local variance — no single miner can meaningfully accelerate a timeout by manipulating block timestamps. A delay of N DAA units translates to a predictable real-world duration.

Compute budget

Every covenant path consumes a compute budget — a cap on the computational work a single UTXO's validation can demand. This prevents denial-of-service attacks where a pathological script forces nodes into expensive loops. Kaspa Safe vault transitions consume 20 compute units; the dual-signature migrate path uses 30. Kaspa Escrow transactions use 40 units. These limits are network-enforced.

Kaspa Safe: the vault covenant in practice

Kaspa Safe is a non-custodial vault for KAS holders built entirely on a Toccata covenant called vault.sil. The contract implements a seven-path state machine:

PathSignature(s)State transitionPurpose
initiatehot keyVAULT → UNVAULTINGStart withdrawal; destination locks into state
cancelalarm keyUNVAULTING → VAULTCancel during the delay window (anti-theft)
complete*none (keyless)*UNVAULTING → destExecute withdrawal after delay expires
checkinhot keyVAULT → VAULTReset the inheritance timer ("I'm alive")
inheritAuto*none (keyless)*VAULT → heirAuto-inherit after dead-man timeout
inheritSignedheir keyVAULT → heirHeir claims manually
migratehot + alarmany → anyFull-owner exit: key rotation, vault upgrade, or immediate withdrawal

The state payload is two fields: mode (0 = VAULT, 1 = UNVAULTING) and dest (the 36-byte version-prefixed script pubkey of the withdrawal destination). Calling initiate writes the destination into the state — it cannot be changed until the withdrawal either completes or is cancelled.

The key design property: keyless paths (complete, inheritAuto) can be broadcast by *anyone* — including the Kaspa Forge server — because the funds can only go where the covenant already dictates. The server can trigger transactions but never touches keys or controls destinations. If Kaspa Forge disappears entirely, the open-source vaultctl CLI tool and a printed recovery sheet let you interact with the vault directly against any Kaspa node (v2+). See how the vault works for a full walkthrough.

Try Kaspa Safe — create a vault with a withdrawal delay and alarm key in under five minutes. On-chain operations are free forever; the optional Telegram alarm costs 100 KAS/year with a 30-day free trial. Create a vault →

Create a vault

In production, the covenant script is compiled at build time and embedded into both the browser-side WASM module and the server binary via Rust's include_str!. All signing happens client-side in the browser (or in the Tauri Android wrapper); private keys never leave the user's device. The server is a thin RPC bridge to a Kaspa node that runs a 10-second watcher loop for alerts and automated keyless transactions.

Kaspa Escrow: covenants for P2P deals

Kaspa Escrow uses a separate covenant, escrow.sil, to hold funds for peer-to-peer transactions. The contract implements a ten-path state machine with two states: ACTIVE (deal in progress) and DISPUTED (awaiting arbitration).

Cooperative paths let the parties resolve without outside help:

  • release — buyer signs, funds go to seller.
  • refund — seller signs, funds go to buyer.
  • mutual — both sign, outputs are flexible (but a fee output is mandatory to prevent bypass of the fee structure).

Dispute and arbitration paths activate when cooperation breaks down:

  • dispute — buyer escalates, transitioning the UTXO to DISPUTED state and starting an arbiter deadline.
  • arbitrateToBuyer, arbitrateToSeller, arbitrateSplit — the designated arbiter key resolves the dispute.

Timeout paths (keyless) handle the "arbiter disappears" scenario: after a DAA-based deadline, funds route to a pre-determined party chosen at deal creation — no signature required, no service dependency.

The contract's key invariant: no spending path — not even the arbitration paths — can send funds to any destination outside {buyer, seller, feeSpk}. The arbiter decides *how* funds split but has zero authority to redirect them elsewhere. This is enforced at the consensus level by every validating node. It is the structural difference from custodial Telegram escrow bots, where the operator physically holds the funds.

Trade-offs and honest limitations

Covenants on Kaspa are powerful, but they carry real constraints:

  • Compute budget ceiling. Complex multi-signature logic is bounded. Adding more paths or heavier validation risks hitting the network's compute limit. The current designs stay well within budget, but expressive power is finite.
  • Silverscript maturity. The language is ^0.1.0 — purpose-built and effective, but young. Tooling, documentation, and third-party audit coverage are still developing. Kaspa Safe's contract is at v3; a v4 revision is planned ahead of an external audit.
  • State size constraints. Each covenant UTXO carries a small state payload (mode flags, destination bytes, pubkeys). Complex metadata lives off-chain. This keeps validation lean but limits what the contract can "remember."
  • Audit status. As of writing, neither vault.sil nor escrow.sil has undergone an external security audit. The contracts have 25+ native VM equivalence tests and a 52-case selftest suite (escrow), but "tested by the builders" is not the same as "audited independently." Kaspa Safe's v4 is earmarked for external review.
  • Beta product limits. Kaspa Escrow caps deal sizes at 50–10,000 KAS during its beta period, and the AI mediator verdict is non-binding — it only executes if a party signs it or the human arbiter intervenes. These are intentional guardrails.
  • No general-purpose computation. Covenants are not Turing-complete smart contracts. There is no persistent storage across UTXOs, no re-entrancy, no inter-contract calls. Each UTXO is an isolated state machine. This limits expressiveness but eliminates entire classes of exploits that plague account-based systems.

The honest summary: covenants on Kaspa give you programmable, consensus-enforced spending rules without handing keys to anyone. The trade-off is that logic must fit within a fixed compute budget and express itself through a small state machine per UTXO. For vaults, escrow, and inheritance — the use cases where "where can the money go" matters more than "what can the contract compute" — that trade-off works.

FAQ

What is a covenant in cryptocurrency?

A covenant is a spending condition attached to a UTXO that constrains not just who can spend it, but where the funds can go and when. Unlike a simple signature check, a covenant enforces rules about the outputs of a future transaction.

Are Kaspa covenants live on mainnet?

Yes. The Toccata upgrade brought covenant support to Kaspa's mainnet. Kaspa Safe and Kaspa Escrow both operate on live Toccata covenants today.

Can the covenant developer steal my funds?

No. A covenant is an on-chain script compiled before funds are sent. The developer cannot modify it after deployment. Each spending path specifies exactly which keys (or keyless conditions) authorize movement, and exactly where funds must go.

What happens if Kaspa Forge goes offline?

Vaults and escrow deals are on-chain contracts. For Kaspa Safe, you can recover funds using a printed recovery sheet and the open-source vaultctl CLI against any Kaspa v2+ node — no connection to our servers required.

How do covenants differ from Ethereum smart contracts?

Covenants are attached to individual UTXOs (like Bitcoin scripts), not deployed as persistent global state machines. They have no re-entrancy, no inter-contract calls, and a fixed compute budget. This limits expressiveness but dramatically reduces the attack surface.

What is the compute budget for covenant transactions?

Kaspa Safe vault transitions use 20 compute units; the dual-signature migrate path uses 30. Kaspa Escrow transactions use 40. These limits are enforced by the Kaspa network during validation.

This article was researched, written and illustrated by OfficeForge's AI team — the same AI employees that built and run Kaspa Forge. Founder-directed, human-reviewed.

Non-custodial · open source

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