Example Projects

Example Projects

Reference implementations demonstrating common patterns for vProgs and Silverscript development. Each example includes a description, architecture overview, and key file listing.

Note: These examples are forward-looking reference designs based on the vProgs architecture. Implementations will be refined as the SDK matures. Examples marked [Coming Soon] depend on tooling not yet available.


1. Decentralized Exchange (DEX)

A constant-product AMM (Automated Market Maker) built as a vProg with Silverscript covenants for liquidity pool management.

Architecture:

  • vProg: Manages pool state (reserves, LP shares, fee accrual) off-chain with ZK-proven transitions
  • Covenants: Silverscript covenants enforce deposit/withdrawal rules on L1 UTXOs
  • ZK Backend: RISC Zero (based ZK app tier, 10-30s proving)

Key files:

dex-vprog/
  src/
    lib.rs                  # Pool state schema and transition logic
    pool.rs                 # Constant-product AMM math (x * y = k)
    lp_token.rs             # Liquidity provider token accounting
    fees.rs                 # Fee calculation and distribution
  covenants/
    liquidity_pool.ss       # Silverscript: deposit/withdraw LP rules
    swap_order.ss           # Silverscript: swap execution covenant
  tests/
    pool_tests.rs           # AMM invariant tests
    integration.rs          # Full swap lifecycle test

Core transition logic:

pub fn swap(
    pool: &PoolState,
    input_token: Token,
    input_amount: u64,
    min_output: u64,
) -> Result<(PoolState, u64), SwapError> {
    let fee = input_amount * pool.fee_bps / 10_000;
    let input_after_fee = input_amount - fee;

    // Constant product: x * y = k
    let (reserve_in, reserve_out) = pool.reserves(input_token);
    let output = (reserve_out * input_after_fee) / (reserve_in + input_after_fee);

    if output < min_output {
        return Err(SwapError::SlippageExceeded);
    }

    Ok((pool.apply_swap(input_token, input_amount, output, fee), output))
}

2. Multi-Sig Wallet

An M-of-N multi-signature wallet using Silverscript covenants for spending authorization.

Architecture:

  • Pure Silverscript: No vProg needed – covenant logic handles all authorization
  • Pattern: N:M covenant (multiple signers, flexible output structure)
  • Use case: Treasury management, shared custody

Key files:

multisig-wallet/
  covenants/
    multisig.ss             # Main multi-sig covenant
    recovery.ss             # Time-locked recovery path
  scripts/
    deploy.sh               # Deployment script
  tests/
    signing_tests.rs        # Threshold signature tests

Silverscript contract:

pragma silverscript ^0.1.0;

contract MultiSig(
    pubkey[5] signers,      // Up to 5 signers
    int threshold            // M-of-N threshold
) {
    entrypoint function spend(sig[] signatures, int[] signerIndices) {
        // Verify at least M valid signatures
        require(signatures.length >= threshold);

        for (i, 0, signatures.length, 5) {
            int idx = signerIndices[i];
            require(idx >= 0);
            require(idx < 5);
            require(checkSig(signatures[i], signers[idx]));
        }
    }

    // Emergency recovery after 90 days with any single signer
    entrypoint function emergencyRecover(sig singleSig, int signerIdx) {
        require(this.age >= 90 days);
        require(signerIdx >= 0);
        require(signerIdx < 5);
        require(checkSig(singleSig, signers[signerIdx]));
    }
}

3. Dutch Auction

A descending-price auction where the price decreases over time until a buyer accepts.

Architecture:

  • Silverscript covenant: Enforces price schedule and settlement rules
  • Time-based pricing: Uses this.age for price decay
  • Pattern: 1:1 transition (auction state updates) or direct spend (purchase)

Key files:

dutch-auction/
  covenants/
    auction.ss              # Main auction covenant
    settlement.ss           # Post-auction settlement
  tests/
    price_decay_tests.rs    # Verify price schedule

Silverscript contract:

pragma silverscript ^0.1.0;

contract DutchAuction(
    pubkey seller,
    int startPrice,         // Starting price in sompis
    int reservePrice,       // Minimum price (floor)
    int duration,           // Auction duration in seconds
    int decayRate           // Price drop per second
) {
    // Buy at the current price
    entrypoint function buy(sig buyerSig, pubkey buyer) {
        // Calculate current price based on elapsed time
        int elapsed = this.age;
        int priceDrop = elapsed * decayRate;
        int currentPrice = startPrice - priceDrop;

        // Enforce reserve price floor
        if (currentPrice < reservePrice) {
            currentPrice = reservePrice;
        }

        // Buyer must pay at least the current price
        // First output goes to seller
        require(tx.outputs[0].value >= currentPrice);
    }

    // Seller can cancel the auction at any time
    entrypoint function cancel(sig sellerSig) {
        require(checkSig(sellerSig, seller));
    }
}

4. Escrow Service

A trustless escrow using covenants for conditional fund release with optional arbitration.

Architecture:

  • Silverscript covenant: Three-party escrow (buyer, seller, arbiter)
  • Release conditions: Mutual agreement or arbiter decision
  • Timeout: Auto-refund to buyer after expiry

Key files:

escrow-service/
  covenants/
    escrow.ss               # Main escrow covenant
  tests/
    escrow_tests.rs         # Lifecycle tests (deposit, release, dispute, timeout)

Silverscript contract:

pragma silverscript ^0.1.0;

contract Escrow(
    pubkey buyer,
    pubkey seller,
    pubkey arbiter,
    int timeout             // Auto-refund timeout in seconds
) {
    // Seller delivers, buyer confirms release
    entrypoint function release(sig buyerSig) {
        require(checkSig(buyerSig, buyer));
        // Funds go to seller (enforced by output check)
    }

    // Buyer requests refund, seller agrees
    entrypoint function refund(sig sellerSig) {
        require(checkSig(sellerSig, seller));
        // Funds return to buyer
    }

    // Arbiter resolves a dispute
    entrypoint function arbitrate(sig arbiterSig, bool releaseToSeller) {
        require(checkSig(arbiterSig, arbiter));
        // Arbiter decides: funds go to seller or buyer
    }

    // Auto-refund after timeout
    entrypoint function timeoutRefund(sig buyerSig) {
        require(checkSig(buyerSig, buyer));
        require(this.age >= timeout);
        // Funds return to buyer after timeout
    }
}

5. DAO Governance

A decentralized governance system combining a vProg for proposal management with Silverscript covenants for vote-weighted treasury spending.

Architecture:

  • vProg: Manages proposal state, vote tallying, and execution queue off-chain
  • Covenants: Silverscript covenants enforce treasury spending rules based on vProg state
  • ZK Backend: RISC Zero (aggregated vote proof)
  • Pattern: Vote results are proven via ZK; treasury covenant checks the proof

Key files:

dao-governance/
  src/
    lib.rs                  # Governance state schema
    proposal.rs             # Proposal lifecycle (create, vote, execute)
    voting.rs               # Vote tallying and quorum logic
    treasury.rs             # Treasury allocation rules
  covenants/
    treasury.ss             # Silverscript: treasury spending covenant
    membership.ss           # Silverscript: membership token rules
  tests/
    governance_tests.rs     # Proposal lifecycle tests
    quorum_tests.rs         # Quorum and threshold tests

Core governance logic:

#[derive(BorshSerialize, BorshDeserialize)]
pub struct Proposal {
    pub id: u64,
    pub title: String,
    pub recipient: AccountId,
    pub amount: u64,
    pub votes_for: u64,
    pub votes_against: u64,
    pub deadline: u64,
    pub status: ProposalStatus,
}

pub fn tally_votes(proposal: &Proposal, quorum: u64) -> ProposalStatus {
    let total_votes = proposal.votes_for + proposal.votes_against;
    if total_votes < quorum {
        return ProposalStatus::QuorumNotReached;
    }
    if proposal.votes_for > proposal.votes_against {
        ProposalStatus::Passed
    } else {
        ProposalStatus::Rejected
    }
}

Treasury covenant (Silverscript):

pragma silverscript ^0.1.0;

contract Treasury(bytes verificationKey, int quorum) {
    // Execute a passed proposal by spending treasury funds
    // Requires a ZK proof that the vote tally is correct
    entrypoint function execute(
        bytes proof,
        bytes32 proposalHash,
        int amount
    ) {
        // Verify the ZK proof that the proposal passed
        bytes publicInputs = encodePublicInputs(proposalHash, amount);
        require(zkVerify(verificationKey, proof, publicInputs));

        // Output the specified amount to the proposal recipient
        require(tx.outputs[0].value == amount);
    }
}

6. Chess Game (Multi-Contract Flow Demo)

A fully on-chain chess game demonstrating Multi-Contract Flows (MCF), Inter-Covenant Communication (ICC), and covenant families. This is the reference example for building complex multi-party applications on Kaspa’s UTXO model.

Architecture:

  • Pure Silverscript: All game logic runs on L1 via covenant state machines – no vProg needed
  • Covenant family: All contracts share a single KIP-20 Covenant ID
  • MCF patterns: Multiplexing (mux/worker) + role system (league/player/game)
  • ICC: Player covenants authorize moves by co-signing transactions with game covenants

Contract roles:

Contract Role Lifecycle
League Root allocator, public registration lane Persistent
Player Durable identity, funds shell, score record Persistent
Mux Owns board state, authenticates moves, routes to workers Per-game
Worker (x N) Validates one specific move type (pawn, castle, en passant, etc.) Stateless
Settle End-of-game settlement, score updates, fund distribution Per-game

Key files:

chess-covenant/
  covenants/
    league.ss               # Registration and matchmaking
    player.ss               # Identity, funds, score tracking
    mux.ss                  # Board state owner, move router
    worker_pawn.ss          # Pawn move validation
    worker_castle.ss        # Castling validation
    worker_enpassant.ss     # En passant validation
    settle.ss               # Game settlement and scoring
  tests/
    move_tests.rs           # Individual move validation
    game_lifecycle.rs       # Full game: register → play → settle
    icc_tests.rs            # Cross-covenant authorization tests

How a move flows (MCF multiplexing):

1. Player signs a transaction including their Player UTXO + Mux UTXO
2. Mux authenticates (ICC: Player covenant co-authorizes)
3. Mux reads the move selector → routes to correct Worker
4. Worker validates the specific move against chess rules
5. Transaction outputs: updated Mux (new board state) + recreated Player

Silverscript mux contract (simplified):

pragma silverscript ^0.1.0;

contract ChessMux(
    bytes32 player_template,     // Template selector: Player role
    bytes32 worker_templates[6], // Template selectors: one per piece type
    bytes32 board_state          // Current board hash
) {



---

## 7. ZK Rollup Covenant (KIP-21)

A complete end-to-end example of a ZK rollup covenant built on the KIP-21 partitioned sequencing commitment. It demonstrates the full lifecycle from L1 transactions to rollup execution and L1 exits, serving as a powerful starting point for building with vProgs.

**Architecture:**

- **vProg:** Executes L2 transfers and state updates off-chain.
- **Covenants:** Manages the canonical bridge, verifying ZK proofs for deposits and withdrawals.
- **ZK Backend:** RISC Zero (STARK) and Groth16.
- **Performance Target:** Demonstrates up to 1,000 transactions per second (TPS) on L2.

**Key features:**

- Full deposit-transfer-withdraw cycle
- Sparse Merkle Tree for L2 account state
- Blake3 hashing for high-performance sequencing commitments
- Forward compatibility: efficiently filters legacy transactions by checking the transaction version in the KIP-21 commitment

    #[covenant.singleton(mode = transition)]
    entrypoint function makeMove(
        int pieceType,           // Selector: which worker to route to
        int fromSquare,
        int toSquare,
        sig playerSig
    ) : (bytes32 new_board_state) {
        // ICC: verify Player covenant is co-input in this transaction
        // (Player covenant independently verifies the user's signature)
        require(hasCovenantInput(player_template));

        // Route to the correct worker via template selector
        require(hasCovenantInput(worker_templates[pieceType]));

        // Worker validates the move; if we reach here, it passed
        // Compute new board state
        return applyMove(board_state, fromSquare, toSquare);
    }
}

Note: This example is based on the SilverScript Chess Covenant demo presented by the Kaspa development team. The actual implementation may differ in specifics as the language and tooling evolve.


Running the Examples

# Clone the examples (once available)
git clone https://github.com/kaspanet/vprogs-examples.git

# Build all examples
cd vprogs-examples
cargo build --release

# Run tests for a specific example
cargo test -p dex-vprog

# Compile Silverscript covenants
silverscript compile dex-vprog/covenants/liquidity_pool.ss

[Coming Soon] The vprogs-examples repository will be published as SDK tooling stabilizes.