Covenants became first-class citizens on Kaspa with the Toccata hard fork in June 2026. Covenants is an umbrella term for the building blocks that fork introduced.
This page introduces the concept, then describes the byte-level program model that the rest of the Covenants group in the sidebar builds on.
The idea
Ordinarily, a coin’s only spending condition is ownership. Whoever holds the key can send the coins anywhere, in any amount.
A covenant attaches a second kind of rule: constraints on what the spending transaction is allowed to do.
The rule is not stored in an external database, and it is not enforced by a third party. It is part of the coins themselves, and the network checks it every time someone tries to spend them.
A covenant can also require that the remaining value be re-locked under the same rules, which makes the rule persist across spends:
The rules do not only permit or deny the spend - they require the leftover value to be re-locked under the same rules.
What covenants enable
Without covenants, a coin’s rules end the moment it is spent. A locking script can require that Alice authorize a spend, but it cannot constrain how she spends.
This limitation is why UTXO chains such as Bitcoin have historically not supported features that are common on account-based chains. Covenants remove it:
| What it enables | Why it needs covenants |
|---|---|
| Tokens | A token is just a rule that says “the total can never change and only the owner may move it” - and that rule has to survive every transfer |
| Vaults | “Withdrawals must sit in a visible waiting period first, and can be cancelled during it” - the delay must persist across spends |
| Escrow | Funds that can only move to one of a few pre-agreed destinations |
| Time-delayed spending | Coins that cannot move until a certain point |
| Whitelisting | Funds that can only ever be sent to approved recipients |
| Congestion control | Committing now to a payout structure that can be settled later |
Many of these examples come from KIP-17, the proposal that introduced the covenant opcodes.
How it differs from a smart contract
On account-based chains such as Ethereum, a program is a contract: code at an address, holding state, that anyone can call.
Kaspa uses a different model.
| Account-based chains | Kaspa covenants | |
|---|---|---|
| Where state lives | In one shared global account | Inside individual coins |
| What a “program” is | Code at an address that anyone calls | Rules travelling with specific coins |
| How it advances | A call mutates shared state | A spend consumes coins and creates successors carrying the updated state |
| Parallelism | Contract calls contend for the same state | Independent coins are spent independently - no contention |
This design trades coordination for parallelism. Because there is no shared global state, independent coins can be spent concurrently without contention. In exchange, interactions between many parties must be arranged as explicit transactions.
Covenants are also not deployed the way contracts are. There is no contract address to send funds to. A covenant exists only as coins locked under its rules; if the last such coin is spent without a successor, the covenant no longer exists.
Two building blocks
Covenants combine two capabilities.
Introspection lets a coin’s rules examine the transaction that is spending it. Without introspection, a rule can only verify a signature. With it, a rule can check where the value is going and in what amounts, and reject the spend if the conditions are not met. This arrived through KIP-10 and was substantially expanded by KIP-17.
Covenant IDs solve a separate problem: identity. Rules alone cannot distinguish a genuine coin from an imitation. Anyone can copy a token’s rules, create their own coins under them, and claim to hold the original - the copy would look identical.
KIP-20 addresses this by having the network track lineage. Each covenant gets a unique identity when it is first created, and every successor inherits it. The network verifies the inheritance directly, so a lookalike created separately has a different identity and cannot pass as the original, regardless of how closely its rules match.
Introspection decides whether a spend follows the rules; covenant IDs establish that the coins being spent are genuine.
The core mechanism
A covenant program is a script that contains its own state as literal bytes, and whose address is the hash of those bytes.
Every covenant on Kaspa is built on the consequence of this:
Because the script is the state, and the address is the hash of the script, a covenant can compute the exact address its successor must have - by taking its own bytes, splicing in the new state, and hashing the result.
The script does not need to store anything externally. It reconstructs its successor from bytes it can already read.
How the mechanism works
1. P2SH hides the script until you spend
A Pay-To-Script-Hash output commits only to a 32-byte hash. Nobody can read the script from the chain while the output is unspent. To spend it you must reveal the script (the redeem script) and it must hash to the committed value.
Call that revealed redeem script R. Throughout the KCC documents, R means the entire covenant program.
2. The program carries its state
R contains more than logic. It begins with a run of data pushes holding the covenant’s current values, followed by the code that acts on them:
Spending the output reveals all of it, so the running script can read its current state directly out of its own bytes.
3. Splice new state into the same logic
The logic bytes are the template. Keep them, swap the state, and you have the successor program R_next. Here is the same contract compiled with count = 8:
4. The address follows from the bytes
R_next hashes to a different value than R, so it has a different address:
blake2b(R) = e9c4ef0278b3d9f5d6d234ae89e2e38f30462fb9b9eeb32ed7caa76625552706
blake2b(R_next) = c4497fd43fe47ddf0a83fb58130ad999ce587f0e00a52a5b380c3f51fa6fd511 The script computes that second hash while it is running, wraps it in the standard P2SH script public key, and requires that one of the transaction’s outputs pays to exactly that address. If the spender pays anywhere else, the script fails.
One full transition:
The consumed instance validates its own successor. Consensus does not interpret the contract; the script performs the check.
Vocabulary
KCC1 fixes these terms, and the rest of the series uses them precisely.
| Term | Meaning |
|---|---|
| Covenant | A spending program that inspects transaction context and restricts how this transaction’s outputs may be spent later |
Covenant program (R) | The complete executable byte string, including every embedded value and its current encoded state. The P2SH redeem script |
| Covenant instance | A UTXO locked to a covenant program. Identified uniquely by its outpoint |
| Transition | A transaction consuming one or more covenant instances and creating zero or more continuations |
| Continuation | An output the consumed instance accepts as its successor |
| Template | What is left of R when the state range is removed - an ordered prefix and suffix |
Two distinctions to keep in mind:
- A program is bytes; an instance is a UTXO. Several UTXOs can hold the identical program.
blake2b(R)therefore identifies a contract-in-a-state, not a coin. - A template is shared by every state a contract can be in. It is the closest thing to the contract’s identity that pure script can express, which is why much of KCC1 concerns hashing and authenticating templates.
Where consensus helps
Reconstructing the successor address proves the next output is correct. It does not, on its own, prove that the UTXO you are spending descends from a legitimate origin rather than from a lookalike someone else deployed. Covenant IDs provide that guarantee. The division of responsibility:
- The script proves the successor’s contents are correct.
- Consensus proves the successor’s lineage is correct.
The OpCov* and OpAuth* opcodes let a script query that structure directly. Covenant IDs are covered in depth in Covenant IDs & Bindings.
What the KCC documents standardize
The opcodes and Covenant IDs are consensus primitives. They say what a script is allowed to inspect and enforce, and deliberately say nothing about how a covenant should lay out its data.
That is a convention problem, and conventions are what the KCC (Kaspa Covenant Conventions) documents standardize. Without them, every covenant is a private binary format that only its own author’s tooling can read.
The distinction between what the network enforces and what programs agree on by convention is why the sidebar splits the series into two groups. Breaking a consensus rule causes the transaction to be rejected. Breaking a convention does not; the covenant still works, but other tooling cannot read it.
| Document | Scope |
|---|---|
| KCC1 | Byte layouts and ABI: value encodings, entrypoints and dispatch tags, the P2SH envelope, state and templates, lineage roles, virtual elements |
| KCC2 | How a program ABI declares who controls a covenant, so observers can answer “whose is this?” |
| KCC20 | A fungible-token covenant surface: required state prefix, transfer interface, and a published descriptor |
KCC1 is deliberately independent of any source language or compiler. SilverScript is the reference compiler that produces programs in this shape, and every hex example above is real output from it.
How to read this series
The pages are ordered so each one only relies on the pages before it, and grouped by whether they describe a network rule or a convention.
Consensus - enforced by the network. True of every covenant, whatever conventions it follows.
| Page | What it adds |
|---|---|
| Covenant Opcodes | The full opcode surface a covenant can call |
| Covenant IDs & Bindings | KIP-20 lineage - how a covenant gets a forgery-proof identity |
Conventions - the KCC documents. Agreements about byte layout that make covenants interoperable.
| Page | What it adds |
|---|---|
| The P2SH Covenant Envelope | How R is committed to, revealed, and executed |
| The Value ABI | How typed values become bytes - the alphabet everything else is written in |
| Entrypoints & Dispatch | How one program exposes several callable branches |
| State, Templates & Continuations | How state is carved out of R and spliced back in |
| Template Views & Virtual Elements | Partial state mutation, and committing to data too large to embed |
| Leaders & Delegators | Coordinating a transition across several covenant inputs |
| Control Principals | KCC2 - declaring who controls a covenant |
| KCC20 Fungible Tokens | The whole stack applied to a real token standard |
If you only read two pages, read Covenant IDs & Bindings and State, Templates & Continuations. Together they cover the most commonly misunderstood concepts.
Current status
The primitives are live on mainnet. You can watch adoption directly:
The tooling above them is newer. Writing covenants in raw script is impractical, so most work goes through SilverScript, a higher-level language that compiles down to it, with Argent layered above for multi-contract applications.
KCC1, KCC2, and KCC20 are all Draft, and SilverScript is explicitly experimental - its authors recommend testnet-10 only for now. Where the current compiler and the draft specs differ, this series says so on the page where it matters. The primitives underneath them are not draft; they have been active on mainnet since Toccata.
Working examples
Runnable covenant code, useful for seeing the primitives exercised end to end:
covenant_id.rs- Covenant ID genesis and continuation, in rusty-kaspacovenants.rs- introspection-based covenants, in rusty-kaspaforced_recipient.py- building a covenant transaction with the Kaspa Python SDKcounter.py- a stateful covenant walked through real transitions on testnet-10- SilverScript example contracts - including
kcc20.silandkcc20-minter.sil - The SilverScript KCC20 book - a full walkthrough of the token and minter contracts
Specifications
The KIPs are merged and active on mainnet. The KCCs are open pull requests against the kccs repository - nothing is merged there yet, so the PR is the document.
| Spec | Covers |
|---|---|
| KCC1 | Covenant definition, concepts, byte layouts and ABI |
| KCC2 | Control principal references in program ABIs |
| KCC20 | Fungible token covenant specification (discussion thread) |
| KIP-10 | New transaction opcodes for enhanced script functionality |
| KIP-16 | New transaction opcodes for verifiable computation (the ZK precompile) |
| KIP-17 | Covenants and improved scripting capabilities |
| KIP-20 | Covenant IDs |
Going deeper
Conceptual
- Programmability - how covenants fit alongside zero-knowledge proofs
- Toccata hard fork - what shipped, and when
- UTXO Model - the coin model covenants build on
- KIPs - the proposals themselves
- KIP-21 explained on Kaspa.com
Prior art
Covenants are a long-running idea in the UTXO world, and much of the design vocabulary comes from Bitcoin research:
- BIP-119 (
OP_CHECKTEMPLATEVERIFY), BIP-345 (OP_VAULT), BIP-347 (OP_CAT) - CAT Protocol - covenant-based fungible and non-fungible tokens
- Covenant use cases and UTXOs.org
- Awesome OP_CAT
- ZK covenants and verifiable programs (vprogs)