Skip to content

Latest commit

 

History

History
97 lines (76 loc) · 4.14 KB

File metadata and controls

97 lines (76 loc) · 4.14 KB

System Architecture

On-chain workplace mutual-aid pool: coworkers save together and borrow with two guarantors who accept partial liability on default.

The program enforces membership state, savings, loan limits (3× savings), co-sign before disbursement, repayment, cancellation, permissionless due-date default settlement, and exit only when obligations are clear. Who may join and when a default is justified stay off-chain; on-chain code enforces mechanics and fund safety.

Account hierarchy

                    Pool PDA
                        │
                        ▼
                   Vault PDA
                        │
        ┌───────────────┼───────────────┐
        ▼               ▼               ▼
   Member PDA      Member PDA      Member PDA
        │               │               │
        ▼               │               │
    Loan PDA            │               │
                        │               │
              (guarantor members) ──────┘

Core accounts

Account Seeds Role
Pool ["pool", admin, pool_name] Config, aggregate counters
Vault ["vault", pool] SPL token custody
Member ["member", pool, owner] Savings ledger, obligations
Loan ["loan", pool, borrower, loan_nonce_le] Pending → Active → closed on full repay/default

PDA helpers: kzp_mini::utils::pda · CLI: cli/src/pda.rs.

Instructions

Instruction Purpose
initialize_pool Admin creates pool + SPL vault
join_pool Pay entry fee, open member PDA
deposit_savings Credit savings; tokens to vault
request_loan Open pending loan (≤ 3× savings, two guarantors)
co_sign_loan Guarantor co-signs; disburses when both sign
repay_loan Partial or full repayment
cancel_loan Borrower cancels pending loan
withdraw_cosign Guarantor revokes partial co-sign
settle_default Permissionless due default; 50/50 guarantor split
exit_pool Withdraw savings; close member PDA

Full account metas: INSTRUCTIONS.md. Field layouts: STATE.md.

Traditional ↔ on-chain mapping

Traditional concept On-chain implementation
Pool / cash box Pool PDA + vault PDA
Member record Member PDA (savings_balance, obligations)
Loan application Loan PDA lifecycle
Two guarantors guarantor_a / guarantor_b; both co-sign to disburse
Partial approval guarantor_*_signed + pending_guarantee_count
Disbursement co_sign_loan CPI when vault ≥ principal
Repayment repay_loan CPI + counter updates
Default settle_default - 50/50 reserved savings ledger settlement
Leave pool exit_pool pays savings, closes PDA

Code layout

programs/kzp-mini/src/
├── lib.rs              #[program] dispatch → instructions::*::handle
├── state.rs            Pool, Member, Loan, LoanStatus
├── instructions/       Anchor account constraints + one handle per instruction
├── operations/         Pure rules/math (unit-tested)
└── utils/              PDA seeds and helpers

Design split: instructions/ = account validation and orchestration · operations/ = pure business rules testable without Anchor contexts.

The file instructions/withdraw_co_sign.rs maps to the withdraw_cosign instruction name.

Loan lifecycle

Pending → Active → full repay (account closed)
                 ↘ due default (account closed)
Pending → cancel_loan (account closed)
Actor Escape hatch while Pending
Borrower cancel_loan
Guarantor withdraw_cosign

Pending vs active guarantee counts: partial co-sign only increments pending obligations; active counts and loan-local backing are set after both co-signs and successful disbursement.

See ACCOUNTING.md for ledger vs vault. See SECURITY.md for trust boundaries.