Kinlock docs

kinlock-contracts

One Soroban contract, kinlock, with two modules: registry (who's a verified payee) and vault (where the money actually sits). This is the only place funds exist outside a user's own wallet.

Entry points

Admin
init, add_attester / remove_attester, add_token / remove_token, set_paused_new_locks, set_caps, upgrade
Registry
register_payee, set_status, update_payout (affects new locks only)
Vault
create_lock, release, refund, decline, bump_lock (permissionless), reads

Rules that don't bend

Invariants (property-tested)

Ten invariants, checked by proptest over random action sequences, not just unit tests:

  1. released + returned ≤ total; equality once the lock reaches a terminal state.
  2. Tranches sum to the lock's total; each tranche's unlock_at ≤ expires_at.
  3. Funds exit only to lock.payout or lock.sender. No third path.
  4. A tranche is released at most once.
  5. Release only happens inside its time window, called by lock.payout.
  6. Refund only on expiry, Revoked status, or Suspended-past-grace.
  7. lock.payout is immutable once the lock is created.
  8. Admin, attester, pause, and allowlist actions never block release, decline, or refund on existing locks.
  9. total_locked equals the sum of remainders across every Open lock.
  10. A failed token transfer reverts all state changes from that call.

On testnet today

Contract
CCSHDQFRYFC3AHV5NE6ULQW6X2CMG5RPANBORDXJGSUD6UKECASJQBRI
Admin
2-of-3 multisig (testnet keys only)
Token
Circle testnet USDC, allowlisted
Test coverage
103 unit / auth / event / TTL tests, plus property tests over 512 random action sequences

Full record: DEPLOYMENTS.md.

Stack

Rust, #![no_std], soroban-sdk. No floating point, no std collections, no unwrap/expect/bare panic! in contract code. USDC via the Stellar Asset Contract (SEP-41), 7 decimals, i128 checked arithmetic throughout.