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
| 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 |
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 (Pending → Active → Repaid / Defaulted) |
| Two guarantors | Both must co-sign before disbursement |
| Default | Admin settle_default; 50/50 guarantor liability |
Deeper domain and mapping: docs/ARCHITECTURE.md.
- One-time entry fee on join
- Member deposits to shared vault
- Per-member savings ledger
- Loan requests with two nominated guarantors
- Partial then full co-sign
- Automatic disbursement when both guarantors approve
- Loan cap at 3× member savings
- One active loan per borrower
- Up to five guarantees per member
- Exit blocked while borrowing or guaranteeing
- Pool initialization and SPL mint binding
- Default settlement with guarantor SPL recovery
Program ID: GsjUnBFvYtcxNwCrydPUjQTngGTqdx5v7APnWahnqwkx
- 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 lifecycleRust 1.89, Solana CLI 3.x, Anchor 1.0.2, cargo-nextest. Full toolchain notes: docs/GETTING_STARTED.md.
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 --releaseKeypairs are local-only - see keys/README.md.
bash scripts/deploy.sh devnetcargo run -p kzp-cli --release -- configCommands 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.
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
Two parallel views:
- SPL vault - actual token balance
- Ledger -
pool.total_savingsandmember.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.
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 |
- Membership and savings state
- Loan limits and guarantor rules
- Co-sign before disbursement
- Vault liquidity checks
- Arithmetic safety (
checked_add/checked_sub)
- 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.
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.
| 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.shConventions: tests/README.md.
| 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.
| 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 |
- 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
bash scripts/ci.shBefore opening a PR: cargo fmt, cargo clippy, cargo nextest, anchor build. See docs/GETTING_STARTED.md for toolchain details.
MIT