ChiaLispProject

A comprehensive guide to learning ChiaLisp for Chia blockchain development


Project maintained by MarvinQuevedo Hosted on GitHub Pages — Theme by mattgraham

Chapter 6: Advanced Real-World Examples

In this chapter we move beyond toy examples and build five practical systems that demonstrate how ChiaLisp puzzles solve real problems. Each example includes:

Prerequisites: You should be comfortable with currying, inner puzzles, conditions, announcements, and Python drivers (Chapters 1-5).


Table of Contents

  1. Escrow System
  2. Savings Account
  3. Lottery / Raffle
  4. Token Vesting
  5. Simple Voting System

1. Escrow System

Files: examples/escrow/escrow.clsp examples/escrow/escrow_driver.py

Concept and Real-World Use Case

An escrow is a financial arrangement where a third party holds funds on behalf of two transacting parties. The funds are released only when predefined conditions are met. This is the backbone of marketplace transactions, freelance payments, and real-estate closings.

On Chia, we implement this as a coin whose puzzle enforces three possible resolution paths:

Path Condition Result
Mutual agreement Buyer AND Seller both sign Funds go to seller (or refund to buyer)
Arbiter decides Arbiter signs + one party signs Arbiter directs funds
Timeout Block height exceeds deadline Buyer gets automatic refund

How the Puzzle Logic Works

The escrow puzzle is curried with five parameters:

The solution provides a mode argument:

  1. Mode 0 – Mutual Release: Both buyer and seller agree. The puzzle requires AGG_SIG_ME from both BUYER_PUBKEY and SELLER_PUBKEY. Funds are sent to SELLER_PUZZLE_HASH.

  2. Mode 1 – Arbiter Decision: The arbiter steps in. The puzzle requires AGG_SIG_ME from ARBITER_PUBKEY and the solution specifies the destination puzzle hash. This allows the arbiter to send funds to either party.

  3. Mode 2 – Timeout Refund: No signatures required beyond the buyer’s. The puzzle checks ASSERT_HEIGHT_RELATIVE against TIMEOUT_HEIGHT and sends funds back to BUYER_PUZZLE_HASH.

Announcements are used so that when the escrow is resolved, the buyer’s or seller’s wallet coin can ASSERT_COIN_ANNOUNCEMENT to confirm the escrow coin was spent in the same bundle.

Security Considerations

Driver Interaction

The Python driver (escrow_driver.py) handles:

  1. Creating the escrow: Currying parameters into the puzzle, creating the coin.
  2. Releasing funds: Building the spend bundle for mutual agreement or arbiter decision.
  3. Timeout refund: Building the spend bundle that asserts height and refunds to buyer.

The driver assembles the correct CoinSpend and pairs it with the appropriate aggregated signature.


2. Savings Account

Files: examples/savings/savings_account.clsp examples/savings/savings_driver.py

Concept and Real-World Use Case

A savings account that enforces withdrawal discipline:

This is useful for personal savings discipline, treasury management for DAOs, or any scenario where you want to prevent impulsive large withdrawals.

How the Puzzle Logic Works

The puzzle uses a singleton-like pattern to maintain state. The coin always recreates itself with updated parameters.

Curried parameters:

Solution modes:

  1. Mode 0 – Deposit: The coin is spent and recreated with the same puzzle hash but a higher amount. The difference is the deposit. Owner signature required.

  2. Mode 1 – Partial Withdrawal: Owner can withdraw up to WITHDRAWAL_LIMIT_PERCENT of the current balance. The puzzle enforces:
    • ASSERT_HEIGHT_RELATIVE for the cooldown period
    • The withdrawal amount is at most the allowed percentage
    • A new coin is created with the remaining balance and an updated LAST_WITHDRAWAL_HEIGHT
  3. Mode 2 – Emergency Withdrawal: Owner can withdraw the full balance after the emergency timelock. The puzzle enforces ASSERT_HEIGHT_RELATIVE with the longer timelock.

Security Considerations

Driver Interaction

The driver tracks the singleton-like coin, computes allowed withdrawal amounts, and builds spend bundles for each operation mode.


3. Lottery / Raffle

Files: examples/lottery/lottery.clsp examples/lottery/lottery_driver.py

Concept and Real-World Use Case

A decentralized lottery where:

  1. Players buy tickets by sending XCH to the lottery coin.
  2. After a deadline, anyone can trigger the draw.
  3. The winner is selected using on-chain randomness (parent coin ID + block height).
  4. The prize pool is sent to the winner.

This can be used for raffles, giveaways, or any fair random selection process.

How the Puzzle Logic Works

The lottery uses two phases, each with its own puzzle:

Phase 1 – Ticket Sales (the lottery coin)

Curried parameters:

When a player buys a ticket, the coin is spent and recreated with the player’s puzzle hash appended to TICKET_LIST and the amount increased by TICKET_PRICE.

Phase 2 – Draw

After DEADLINE_HEIGHT, anyone can trigger the draw. The puzzle:

  1. Asserts ASSERT_HEIGHT_RELATIVE to confirm the deadline has passed.
  2. Computes a pseudo-random index: (sha256 MY_COIN_ID) mod (length TICKET_LIST).
  3. Sends the prize pool to the winner’s puzzle hash.
  4. A small operator fee (e.g., 2%) is sent to the operator.

Security Considerations

Driver Interaction

The driver handles ticket purchases (spending and recreating the lottery coin), triggering the draw, and distributing prizes. It tracks the evolving lottery coin as tickets are purchased.


4. Token Vesting

Files: examples/vesting/vesting.clsp examples/vesting/vesting_driver.py

Concept and Real-World Use Case

Token vesting is standard in crypto projects: team members, investors, or advisors receive tokens that unlock gradually over time. This prevents dumping and aligns long-term incentives.

Our vesting schedule:

How the Puzzle Logic Works

Curried parameters:

Solution provides the claim_amount and the current block_height.

The puzzle logic:

  1. Before cliff: Spending is completely blocked (ASSERT_HEIGHT_RELATIVE would fail since puzzle requires height >= CLIFF_HEIGHT).

  2. After cliff, during vesting:
    • Calculate elapsed blocks since vesting start: elapsed = current_height - VESTING_START_HEIGHT
    • Calculate vested amount: vested = (TOTAL_AMOUNT * elapsed) / TOTAL_VESTING_PERIOD
    • Available to claim: available = vested - CLAIMED_AMOUNT
    • The puzzle verifies claim_amount <= available
    • Creates a new coin with updated CLAIMED_AMOUNT and reduced balance
  3. After full vesting period: All remaining tokens can be claimed.

Security Considerations

Driver Interaction

The driver calculates the current vested amount based on block height, determines how much is claimable, and builds the spend bundle. It also provides a vesting_schedule() method that shows a human-readable timeline.


5. Simple Voting System

Files: examples/voting/voting.clsp examples/voting/voting_driver.py

Concept and Real-World Use Case

A simple on-chain voting system where:

  1. A proposal is created with a set of options.
  2. Token holders cast votes by spending coins that reference the proposal.
  3. Votes are tallied via announcements.
  4. After the voting period, the result is determined.

This is useful for DAO governance, community decisions, or any scenario requiring transparent, verifiable voting.

How the Puzzle Logic Works

The system has two puzzle types:

Proposal Puzzle (the ballot box)

Curried parameters:

The proposal coin accepts votes and recreates itself with updated tallies. After the deadline, it can be finalized to announce the result.

Vote Puzzle (individual vote)

When a voter wants to cast a vote, they create a coin announcement containing:

The proposal coin uses ASSERT_COIN_ANNOUNCEMENT to verify each vote in the same spend bundle, then recreates itself with updated tallies.

Security Considerations

Driver Interaction

The driver creates proposals, submits votes (coordinating the vote coin spend with the proposal coin spend in the same bundle), and reads the final tally from the last proposal coin state.


Running the Examples

Each example is self-contained. To study them:

  1. Read the .clsp file and its comments to understand the on-chain logic.
  2. Read the _driver.py file to understand how a wallet or application interacts with the puzzle.
  3. Try modifying parameters (timeouts, percentages, etc.) to see how the behavior changes.

In the next chapter, we will combine many of these patterns into a full CAT Staking System as the capstone project.