Skip to content

vvylym/kzp-mini

Repository files navigation

KZP Mini

KZP Mini is a Solana implementation of a workplace mutual-aid fund (Kasa Zapomogowa Pracownicza).

Members:

  • join a shared pool
  • deposit savings
  • request loans with two guarantors
  • repay obligations
  • withdraw savings and leave

The protocol enforces financial mechanics on-chain while allowing membership policy and governance to remain off-chain. Built in Rust using Anchor.

Superteam Poland submission - entry for Build everyday real-world systems as on-chain Rust programs on Superteam Earn.

Repository: github.com/vvylym/kzp-mini

At a glance

Property Value
Blockchain Solana (devnet deployed)
Language Rust 1.89
Framework Anchor 1.0.2
Loan model Two guarantors, 3× savings cap
Savings model Shared SPL vault + ledger
Client kzp CLI
License MIT

Why KZP?

Traditional workplace savings associations rely on spreadsheets, manual bookkeeping, paper signatures, and committee decisions. That creates opaque balances, delayed settlement, manual verification, and dispute risk.

KZP Mini replaces administrative coordination with on-chain enforcement.

Concern Traditional handling Friction
Membership HR roster, payroll deductions Manual roster upkeep
Savings Spreadsheet per member Opaque balances
Loans Committee + verbal guarantees Signatures disconnected from money
Default Social pressure, delayed settlement No shared rule engine
Exit Manual “all clear” check Error-prone
Traditional concept On-chain implementation
Pool / cash box Pool + Vault PDAs
Member record Member PDA
Loan Loan PDA (PendingActiveRepaid / Defaulted)
Two guarantors Both must co-sign before disbursement
Default Admin settle_default; 50/50 guarantor liability

Deeper domain and mapping: docs/ARCHITECTURE.md.


Key features

Savings

  • One-time entry fee on join
  • Member deposits to shared vault
  • Per-member savings ledger

Lending

  • Loan requests with two nominated guarantors
  • Partial then full co-sign
  • Automatic disbursement when both guarantors approve

Risk controls

  • Loan cap at 3× member savings
  • One active loan per borrower
  • Up to five guarantees per member
  • Exit blocked while borrowing or guaranteeing

Administration

  • Pool initialization and SPL mint binding
  • Default settlement with guarantor SPL recovery

Live devnet demo

Program ID: GsjUnBFvYtcxNwCrydPUjQTngGTqdx5v7APnWahnqwkx

Verified lifecycle

  • Deploy program
  • Initialize pool
  • Join members (admin + two guarantors)
  • Deposit savings
  • Request loan
  • Co-sign (guarantor A, then B)
  • Disburse principal
  • Repay loan
  • Exit pool
Step Transaction
Program deploy explorer
Initialize pool explorer
Admin join explorer
Guarantor A join explorer
Guarantor B join explorer
Deposit savings explorer
Request loan explorer
Co-sign (guarantor A) explorer
Co-sign + disburse (B) explorer
Repay loan explorer
Exit pool explorer

Demo accounts: pool 4nZf8sPfRvKUucN43FirPQ3T3JvvkCo4LFukGYCRL7tg · loan toqwDKpVPAdHPkLSJWyh5yLdDTf7szVEKPRtVNek4bL · mint 9CsRiEPkagzfTLTDhsBhuvfHNXupBugtHzy1wPefTi4V

bash scripts/devnet-demo.sh   # full scripted lifecycle

Quick start

Install

Rust 1.89, Solana CLI 3.x, Anchor 1.0.2, cargo-nextest. Full toolchain notes: docs/GETTING_STARTED.md.

Build

git clone https://github.com/vvylym/kzp-mini.git && cd kzp-mini
mkdir -p target/deploy && cp keys/program.json target/deploy/kzp_mini-keypair.json
NO_DNA=1 anchor build --ignore-keys
cargo build -p kzp-cli --release

Keypairs are local-only - see keys/README.md.

Deploy

bash scripts/deploy.sh devnet

Verify

cargo run -p kzp-cli --release -- config

CLI usage

Commands grouped by role. Full reference: docs/CLI.md.

Role Commands
Pool administrator pool initialize · loan settle-default
Members pool join · pool deposit · pool exit
Borrowers loan request · loan repay · loan cancel
Guarantors loan cosign · loan withdraw-cosign
kzp pool initialize --name "My Pool" --entry-fee 50 --mint <MINT>
kzp pool join --pool <POOL> --entry-fee 50
kzp pool deposit --pool <POOL> --amount 1000000
kzp loan request --pool <POOL> --nonce 1 --amount 500000 \
  --guarantor-a <PUBKEY_A> --guarantor-b <PUBKEY_B>
kzp loan cosign --loan <LOAN>
kzp loan repay --loan <LOAN> --amount 500000
kzp pool exit --pool <POOL>

Global flags: --cluster, --rpc-url, --wallet, --dry-run.


System architecture

                    Pool PDA
                        │
                        ▼
                   Vault PDA
                        │
        ┌───────────────┼───────────────┐
        ▼               ▼               ▼
   Member PDA      Member PDA      Member PDA
        │
        ▼
    Loan PDA
Account Purpose
Pool Admin, mint, counters
Vault SPL token custody
Member Savings, loan/guarantee obligations
Loan Principal, guarantors, status

Instructions (10): initialize_pool · join_pool · deposit_savings · request_loan · co_sign_loan · repay_loan · cancel_loan · withdraw_cosign · settle_default · exit_pool

Details: docs/ARCHITECTURE.md · docs/INSTRUCTIONS.md · docs/STATE.md


Financial model

Two parallel views:

  1. SPL vault - actual token balance
  2. Ledger - pool.total_savings and member.savings_balance

Entry fees fund the vault but not member savings (liquidity buffer). Disburse and exit are fail-closed if vault balance is insufficient.

Full model: docs/ACCOUNTING.md.


Loan lifecycle

Pending → Active → Repaid
                 ↘ Defaulted
Pending → cancel_loan
State Guarantor tracking Escape hatches
Pending pending_guarantees Borrower: cancel_loan · Guarantor: withdraw_cosign
Active active_guarantees Repay or admin settle_default
Repaid / Defaulted Cleared Guarantors may exit when list empty

Security & trust model

Enforced on-chain

  • Membership and savings state
  • Loan limits and guarantor rules
  • Co-sign before disbursement
  • Vault liquidity checks
  • Arithmetic safety (checked_add / checked_sub)

Off-chain / trusted

  • Who may join the pool (workplace policy)
  • Whether a default is justified (admin judgment)
  • SPL mint legitimacy at pool creation

Full threat model: docs/SECURITY.md.


Project structure

programs/kzp-mini/src/
├── instructions/   Anchor account constraints
├── handlers/       CPIs + state updates
├── operations/     Pure business rules (unit-tested)
├── state.rs        Pool, Member, Loan
└── utils/          PDA helpers

cli/                kzp command-line client
tests/              solana-program-test integration suite
docs/               Architecture, CLI, accounting, security
scripts/            ci.sh, deploy.sh, devnet-demo.sh
keys/               Local keypairs (gitignored)

Philosophy: instructions = validation · handlers = orchestration · operations = testable rules without Anchor contexts.


Testing

Layer Coverage
Unit tests programs/kzp-mini/src/operations/
Integration 46 solana-program-test scenarios
Specs BDD criteria in docs/USE_CASES.md
bash scripts/ci.sh

Conventions: tests/README.md.


Documentation

Document Audience Purpose
README.md Everyone Overview and navigation
docs/GETTING_STARTED.md Developers Install, deploy, devnet setup
docs/CLI.md Operators Full CLI by role
docs/ARCHITECTURE.md Reviewers Accounts, instructions, mapping
docs/ACCOUNTING.md Auditors Ledger vs vault, limits
docs/SECURITY.md Auditors Threat model
docs/INSTRUCTIONS.md Integrators Instruction account metas
docs/STATE.md Integrators Account layouts
docs/USE_CASES.md Contributors Acceptance criteria
docs/ERRORS.md Integrators Error codes

Index: docs/README.md.


Limitations & tradeoffs

Topic Choice Implication
Policy vs code Eligibility off-chain Admin can settle_default without on-chain proof
Single admin One pool.admin No multisig in this release
Default split 50/50 (div_ceil on odd amounts) First guarantor pays extra token on odd sums
Loan cap 3× savings, 5 guarantees May block edge cases
Ledger vs vault Both tracked; fail-closed exit/disburse Safer; monitor for drift
Pending loans Only borrower can cancel Abandoned PDAs pay rent until cancelled
Upgrades No migration instruction Schema changes need fresh pool deploy
Toolchain Rust 1.89, Anchor 1.0.2, Solana 3.x Solana 4.x unsupported

Roadmap

Planned

  • Multisig pool administration
  • On-chain governance voting for defaults
  • Accrued yield on member savings (pool-level interest distribution)
  • Dynamic guarantee models (e.g. variable split)
  • Account migration support

Contributing

bash scripts/ci.sh

Before opening a PR: cargo fmt, cargo clippy, cargo nextest, anchor build. See docs/GETTING_STARTED.md for toolchain details.


License

MIT

About

Submission for "Build everyday real-world systems as on-chain Rust programs" challenge by Superteam Poland.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Contributors