Kaspalytics Learn is a work in progress.
Updated: Aug 2, 2026

SilverScript

Writing Kaspa script contracts in SilverScript - compiling to a locking script, building unlocking scripts, and stateful covenants.

SilverScript is a CashScript-inspired language for writing native Kaspa script contracts. You write a contract, compile it to a locking script, and lock funds behind that script’s hash — a P2SH address. To spend them, you call one of the contract’s entrypoints and the tooling turns that call into the unlocking script the node accepts.

For the conceptual background, see SilverScript in Learn.

Experimental. SilverScript, its compiler output, and the SDK bindings are all under active development and subject to breaking changes. Pin your versions, and don’t lock real value behind a contract you haven’t verified end to end on testnet first.

What the tooling gives you

  • Compile SilverScript source into a locking script.
  • Build the unlocking script for an entrypoint call, mapping your arguments to the contract’s ABI.
  • Debug a call locally — simulate the spend and get a source-level failure report with decoded variables, before you spend anything on chain.

Everything after that is ordinary Kaspa work: wrap the locking script in a P2SH address, build and sign the transaction, submit it. See Transactions.

Language support

SilverScript lives in its own Rust workspace, so the surfaces differ by language:

LanguageHow you get it
RustThe silverscript-lang crate — compile_contract and the AST types directly.
Pythonkaspa.experimental.silverscript, a sub-package of the Kaspa SDK.
CLIsilverc, which compiles .sil files to a JSON artifact (bytecode + ABI).
JavaScriptNo binding today. Compile with silverc and load the artifact’s script bytes.

The compiler’s whole interface to the rest of the SDK is script bytes. Compile, read the script, then build the transaction with the core SDK as usual — the compiler never sees an Address or a ScriptBuilder.

When to reach for it

  • Stateful covenants — contracts that carry state from one UTXO to the next: a counter, an escrow, a vault. See Covenants.
  • Custom locking conditions that are awkward to hand-assemble from raw opcodes, where a typed, readable language pays for itself.

If you only need standard P2PK or multisig, you don’t need SilverScript at all.

A contract

A minimal Guard that only lets a spend through when amount exceeds a threshold baked in at compile time:

pragma silverscript ^0.1.0;

contract Guard(int threshold) {
    entry check(int amount) {
        require(amount > threshold);
    }
}

entry marks a branch as externally invocable; plain function declares an internal helper an entry can call.

Syntax change. entry name(...) replaced the older entrypoint function name(...) spelling in SilverScript #187. Contracts written against the old keyword no longer parse on master. The Kaspa Python SDK pins a SilverScript revision from before that change, so entrypoint function may still compile through kaspa.experimental.silverscript until the SDK bumps its pin — write entry either way.

Compile and lock

Compile with the constructor argument threshold = 100, wrap the resulting redeem script in a P2SH lock, and turn that into a fundable address:

use silverscript_lang::ast::Expr;
use silverscript_lang::compiler::{compile_contract, CompileOptions};

let source = r#"
    pragma silverscript ^0.1.0;
    contract Guard(int threshold) {
        entry check(int amount) {
            require(amount > threshold);
        }
    }
"#;

let compiled = compile_contract(source, &[Expr::Int(100)], CompileOptions::default())?;

println!("contract: {}", compiled.contract_name);
println!("compiler: {}", compiled.compiler_version);
println!("script: {} bytes", compiled.script.len());
println!("abi: {:?}", compiled.abi);
import kaspa.experimental.silverscript as silverscript
from kaspa import ScriptBuilder, address_from_script_public_key

SOURCE = """
pragma silverscript ^0.1.0;
contract Guard(int threshold) {
    entry check(int amount) {
        require(amount > threshold);
    }
}
"""

# Compile with the constructor arg threshold = 100.
contract = silverscript.compile(SOURCE, [100])

# The redeem script.
redeem = contract.script

# Wrap it in a P2SH lock and turn that into a fundable address.
spk = ScriptBuilder.from_script(redeem).create_pay_to_script_hash_script()
addr = address_from_script_public_key(spk, "testnet")
# Compile to a JSON artifact containing contract_name, compiler_version,
# script (bytecode), ast, and abi.
silverc guard.sil -o guard.json

# With constructor arguments, supplied as a JSON array of typed expressions:
#   [{"kind": "int", "data": 100}]
silverc guard.sil --constructor-args args.json

Send funds to that address and they’re locked behind the contract.

Spend it

To spend, build the unlocking script for the entrypoint call — check(amount) — and use it as the input’s signature script. The Python bindings take plain Python values (int, bool, str, bytes, lists, dicts) and map them onto the contract’s declared parameter types; passing the wrong type is an error at build time rather than a script failure on chain.

Stateful covenants use a separate call that additionally binds the covenant declaration, so the compiler can enforce the state transition the contract declares.

Debugging

The most useful part of the toolchain. debug_call simulates a spend locally and, on failure, reports which require failed, at which source line, with the decoded values of the variables in scope. There’s also a standalone source-level stepping debugger in the SilverScript workspace:

cargo run -p cli-debugger -- contract.sil \
  --function check \
  --ctor-arg 100 \
  --arg 150

Use it before every on-chain spend. A failed unlock on chain costs a transaction and tells you almost nothing.

Full examples

  • examples/silverscript/counter.py — a stateful Counter covenant end to end on testnet-10. Compiles the contract, funds it, and walks the count through add / subtract transitions, each a real on-chain transaction.
  • SilverScript tutorial — the full language reference: types, control flow, transaction introspection, covenant builtins.
  • Covenant declaration spec — the #[covenant(...)] attribute that generates leader/delegator transitions for you.
  • KCC20 book — the fungible-token convention built on top of it.

Where to next

Kaspalytics strives to provide accurate data - our highest level of effort is given to data validation and maintenance. However, we cannot guarantee 100% accuracy. Data is subject to inaccuracies and change.

Contact | © 2026 Kaspalytics