Skip to content

alrimarleskovar/RoundFinancial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

631 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

RoundFi

Behavioral-credit infrastructure for Solana. RoundFi runs on-chain ROSCAs as a data-acquisition engine: every paid installment mints an on-chain attestation that builds a portable credit identity. The ROSCA is the bait; the behavioral score is the product. Endgame: a high-margin B2B oracle that neobanks and DeFi protocols subscribe to before lending — the Serasa of Web3.

CI Live demo Demo video Pitch video PRs merged Audit-ready · self-audit + threat model Devnet · 3 pools + browser writes

🚀 Live demo · 🎬 Demo (video) · 🎙️ Pitch (video) · 📋 Status (shipped vs roadmap) · 📊 3-min Pitch (EN) · 📊 3-min Pitch (PT) · 📊 Long-form Deck (EN) · 🧱 Architecture · 🔍 Audit Findings (51 SEVs) · 🛡️ Audit-Readiness · 📋 Audit Scope · 🚦 Mainnet Readiness · 📦 Grant bundle

Status: M3 shipped · 4 programs live on devnet · reproducible-build attestation on-chain · mainnet-canary code controls complete (Kamino harvest CPI, TVL caps per-pool + protocol-wide, yield-adapter allowlist + lock-flag, devnet→mainnet network-confusion banner, Squads multisig procedure docs, Civic→Human-Passport PoP migration — validator code shipped; off-chain bridge service planned, see threat model for activation checklist) · Internal pre-audit complete (5-pass red-team + 1 integration-testing wave + 9 follow-up waves through #413, pre-engagement preparation simulating external auditor methodology)51 findings catalogued, 49 🟢 closed, 0 open, 2 🔵 design-intentional (SEV-018 won't-fix, SEV-032 acknowledged) (tracker); SEV-039 closed via the close_member + close_pool_vaults rent-reclaim ceremony; SEV-012 closed — the mplcore path now runs as a REQUIRED litesvm CI lane (tests/_harness/litesvm.ts + tests/litesvm_join_pool.spec.ts, Node-24-pinned to dodge a V8-GC std::bad_alloc); Critical/High 16 of 16 🟢 closed (6 Critical + 10 High, including SEV-034b + SEV-040/041/042 Kamino-spike findings + SEV-047 reputation-farming gate + SEV-049 and SEV-050, the two High liveness locks from the litesvm L1↔L2 parity slice — SEV-049 = skip_defaulted_payout, SEV-050 = removed close_pool's unsatisfiable defaulted-pool guard) · Formal external audit (Adevar / Halborn / OtterSec / Sec3 — selection pending) scoping in progress · 300+ tests across 27 spec files + frontend allowlist + indexer JSON-shape + mainnet-hardening suite (see MAINNET_READINESS.md for full 314+ breakdown) · 6 cargo-fuzz targets on roundfi-math (~9.85B inputs cumulative — 503M historical + 600M afternoon re-validation 2026-05-24 + 8.75B overnight sweep 2026-05-24 (6 targets × 1h each, 0 crashes, coverage stable (saturation reached) in the input space covered by the current corpus)) · Adevar/Halborn/OtterSec/Sec3 engagement + Squads ceremony + bug bounty pending before mainnet GA. _Last updated: May 2026.

Built for the Colosseum Hackathon 2026.


Why RoundFi

DeFi solved trading. DeFi solved liquidity. DeFi never solved credit. The two clearest attempts at on-chain ROSCAs / under-collateralized retail credit both shipped — and both went quiet:

  • WeTrust (Ethereum, 2017–2018) — first on-chain ROSCA, Trusted Lending Circles. Gas costs ate margins, retention collapsed when ETH stalled, and the protocol was the product — no data layer to monetize. Wound down quietly.
  • RociFi (Solana, 2021–2023) — under-collateralized lending with NFT credit scores. The score was program-internal (not portable, not SAS-compatible), B2B distribution never materialized, and liquidator economics broke under volatility. Project sunset.
Protocol Status Sub-collateral Behavior score Retail user Emerging markets Position NFT No prior crypto
Aave / Marginfi live
Goldfinch live ~
Maple / TrueFi live ~
Credix live
WeTrust sunset ~
RociFi sunset ~ ~ ~
RoundFi devnet

The boxes alone don't make us right — Aave, Goldfinch, and Credix are real businesses with billions of TVL between them. What separates RoundFi from the projects that sunset is structural, not feature-list:

  • Phase 3 is the revenue model from day 1, not an afterthought. WeTrust's protocol was the product, so when retention slipped there was nothing left to sell. RociFi's NFT score didn't read outside their pools, so there was no B2B moat. RoundFi treats Phase 1 (ROSCAs) explicitly as the data-acquisition engine for Phase 3 (per-call B2B oracle subscriptions to neobanks + DeFi protocols). The Triple Shield + Yield Cascade exist to keep Phase 1 solvent while the on-chain dataset compounds.
  • Score is SAS-compatible from the first attestation. Every paid installment mints against the Solana Attestation Service schema — the protocol shipped this end-to-end (see roundfi-reputation program + tests/reputation_cpi.spec.ts). On the user-facing side, the /reputacao surface today mixes on-chain reads (real devnet attestations from member-3's contribute and others) with a session-reducer reflection used in Demo Studio mock mode. The portability infrastructure is on-chain; B2B subscription consumers are roadmap (Phase 3). RociFi's score died with RociFi — SAS-compatible attestations exist independent of any front-end going forward.
  • Solvency is mathematical, not aspirational. WeTrust's retention model was "members keep paying because trust." RoundFi's Triple Shield gives a 91.6% Month-1 retention floor as a deterministic property of the contract — encoded in crates/math/src/waterfall.rs and parity-tested against the Stress Lab L1 simulator. Stake decays 50% → 30% → 10% but only after on-chain attestations confirm cycle completion — no honor system.

Security & Audit

Internal pre-audit — May 2026. A 5-pass red-team exercise + 1 integration-testing wave + 9 follow-up waves through #413, run by the RoundFi team simulating external auditor methodology (formal engagement scoping in progress with Adevar / Halborn / OtterSec / Sec3 — selection pending), explicitly designed to surface and close findings before the paid auditor's clock starts. 51 findings catalogued; 49 closed in code (Critical/High 16 of 16 — 6 Critical + 10 High including SEV-034b surfaced by integration-testing wave, SEV-040/041/042 surfaced by the Kamino-spike pre-audit wave, SEV-047 reputation-farming gate from the 2026-05-24 external-audit pass, and SEV-049 + SEV-050, the two High liveness locks from the litesvm L1↔L2 parity slice — SEV-049 closed via skip_defaulted_payout, SEV-050 closed by removing close_pool's unsatisfiable defaulted-pool guard), 0 open, 2 acknowledged-by-design.

Public tracker: docs/security/internal-audit-findings.md. This is not an external-firm attestation — it's our own work, framed in the standard issue-template shape so the formal audit can re-validate quickly against a clean baseline.

Severity Total 🟢 Closed 🟡 Open 🔵 Won't fix / Acknowledged
Critical 6 6 0 0
High 10 10 0 0
Medium 14 14 0 0
Low 12 12 0 0
Informational 9 6 0 3
Total 51 48 0 3

🟢 SEV-049 and SEV-050 — both High liveness locks found by the litesvm L1↔L2 parity slice — are now closed: SEV-049 via the new permissionless skip_defaulted_payout instruction, SEV-050 by removing close_pool's unsatisfiable defaulted-pool guard so a defaulted pool can close. No open findings remain; Critical/High is all-closed.

Highlights from the remediation cycle:

  • SEV-001 (Critical): unvalidated c_token_account in roundfi-yield-kamino::Deposit could redirect Kamino c-tokens to an attacker ATA. Closed by #326 with associated_token::mint + associated_token::authority constraint pinning the protocol-owned ATA.
  • SEV-002 (Critical): GRACE_PERIOD_SECS = 60 devnet patch leaked to main with a pinning test asserting == 60. Reverted to 7 days (#327). Pattern audit (#340) swept every constant and added a floor-guard CI lane (#343) — assert!(GRACE_PERIOD_SECS >= 86_400) catches a regression even if the pinning test is updated to the wrong value.
  • SEV-021 / SEV-022 (High): 7-day propose/cancel/commit timelock on the reputation authority rotation, plus decoupling of core/reputation pause flags so a paused reputation program no longer drags core's contribute/claim_payout CPI flows through the back door (#337).
  • SEV-024 follow-up: 1-day timelock pilot on fee_bps_yield (#347). Direct mutation via update_protocol_config now returns DirectFeeBpsYieldMutationDisabled — callers must use the timelock flow.
  • SEV-029 (High — regression of SEV-016): the partial-release fix in #334 introduced an overpay vector in release_escrow (caller could re-target the same checkpoint and collect a fresh delta). Caught by the W3 internal re-audit; closed by #342 with a math rewrite using cumulative_paid = stake - escrow_balance and 6 negative regression tests (4 unit + 2 proptest invariants) per the new "negative test before merge" gate.
  • SEV-031 (Low): create_pool now runtime-checks the pool viability invariant via the math crate (pool_is_viable(members, installment, credit, sol_bps, escrow_bps)) — same code path used by unit tests and on-chain, no drift.
  • SEV-026 (Low): settle_default cascade math refactored to delegate to roundfi_math::seize_for_default — single source of truth, no inline-vs-crate drift.

Methodology: every Critical / High fix ships with a negative regression test before merge. The constants audit follow-up established a two-layer defense (pinning + floor-guard) so future devnet-shortcut leaks fail loudly in CI rather than embedding silently. Pattern documented in docs/security/constants-audit-2026-05.md.

Remaining surface: SEV-012 (bankrun-in-CI coverage gap) is now CLOSED — the mpl_core path (join_pool / escape_valve_buy) runs as a REQUIRED litesvm CI lane (tests/_harness/litesvm.ts + tests/litesvm_join_pool.spec.ts); a V8-GC std::bad_alloc on Node 20 was fixed by pinning that lane to Node 24. SEV-018 (settle_default deliberately bypasses pause) and SEV-032 (ReputationConfig padding exhausted by SEV-021 additions) are documented design constraints, not vulnerabilities.

Why this matters: a paid external audit costs the team's clock to surface issues a competent red-team would find. By running the methodology ourselves first and closing 49 of 51 findings against a public tracker (Critical/High 16 of 16 — all closed, including SEV-050, the defaulted-pool close_pool liveness lock, fixed by removing the unsatisfiable defaulted-pool guard), the formal external auditor engagement (Adevar / Halborn / OtterSec / Sec3 — selection pending) starts from a state where the obvious paths are already covered — auditor time goes to the harder questions. The commit history is the audit trail; the tracker is the running scorecard.

Companion docs: docs/security/passport-bridge-threat-model.md (off-chain bridge trust boundary), docs/security/economic-config-governance.md (timelock target tiers for all ProtocolConfig fields), docs/operations/kamino-devnet-exercise.md (operational receipt template for the SEV-001 fix), docs/operations/reputation-config-migration.md (re-init procedure for the SEV-021 state-shape change).

Thesis (per the whitepaper)

RoundFi is a behavioral-credit primitive disguised as a savings protocol. The product evolves through three explicit phases — codified in the B2B plan and Expansion plan:

Phase Surface What it does
1 · Liquidity ROSCA pools on Solana Bootstrap users with sub-collateralized credit. Stake ladder 50% → 30% → 10% as reputation graduates.
2 · Reputation SAS attestations + behavioral score Every paid installment mints an immutable attestation; the score becomes a portable credit identity.
3 · B2B data Behavioral oracle API Neobanks, DeFi protocols, and emerging-market lenders subscribe per-call to query the score before extending credit. High-margin endgame.

Phase 1 is the acquisition engine. Phase 3 is the business model. The Triple Shield + Yield Cascade exist to keep Phase 1 solvent while the on-chain dataset compounds. Esusu hit a $1.2B valuation building Phase 2 in Web2; RoundFi does it on-chain with deterministic logic, then sells the data layer.

Core Mechanics

  • Pool shape: 24 members · $600/mo installment · ~$10K credit per cycle (internal pre-audit SEV-025: defaults bumped from $416 to make the pool viable out of the box — pool float 24×600×0.74 = 10_656 USDC ≥ 10_000 credit clears the cycle-0 Seed Draw guard)
  • Reputation ladder (50-30-10 Rule): stake drops 50% → 30% → 10% as members graduate Level 1 → 2 → 3 (Veteran). Veterans unlock 10× leverage.
  • Triple Shield:
    1. Seed Draw — Month-1 retention of 91.6% of capital.
    2. Adaptive Escrow — locks reward portions so debt decreases faster than collateral returns.
    3. Solidarity Vault — 1% of each installment, redistributed as Good Faith Bonus.
  • Yield Waterfall (Kamino adapter, 5–8% APY mainnet target): Protocol → Guarantee Fund → LP Angels → Participants. The Kamino adapter ships real CPIs for both the deposit path (deposit_reserve_liquidity) and the harvest path (redeem_reserve_collateral, redeem-all + redeposit-principal round-trip — closed #233) in programs/roundfi-yield-kamino. Devnet uses the mock adapter (programs/roundfi-yield-mock) for deterministic test cycles; mainnet flips to the kamino adapter via the config.approved_yield_adapter allowlist. Adapter is swap-via-Pool.yield_adapter Pubkey — no core redeploy needed.
  • Escape Valve: positions are dynamic NFTs. Distressed users sell instead of defaulting.
  • Behavioral oracle: every payment is an on-chain attestation (SAS-compatible) — a portable credit identity, the "Serasa of Web3".

Stress Lab (L1 reference impl)

The protocol's economic spec is encoded in a pure-TypeScript actuarial simulator that runs every Triple-Shield rule end-to-end. Lives in sdk/src/stressLab.ts and ships the /lab interactive route. Used as:

  • Reference implementation for the on-chain Anchor programs (M2 of the grant roadmap parity-tests against runSimulation() outputs).
  • Whitepaper-faithful playground — pick credit/members/tier/maturity/APY and watch the matrix unfold. 4 canonical presets (Healthy / Pre-default / Post-default / Cascade) load with one click.
  • Audit panel with full capital-structure breakdown: float + Solidarity Vault + Guarantee Fund (capped at 150% of credit) − outstanding escrow − outstanding stake refund = Net Solvency. Plus the 4-tier yield waterfall (admin fee → GF → 65% LPs → 35% participants).

51 L1 tests green under pnpm run test:economic-parity-l1 covering: input refactor (credit-amount as primary), toggleCell click semantics, escrow gating on default month, stake cashback phase, net-solvency identity, capital structure invariants, mature-group acceleration (5/4/3 → 3/2/1), Escape Valve "E" cell architecture, and the 4-tier waterfall split.

L1 ↔ L2 parity validated on-chain (Healthy preset). The Healthy matrix from runSimulation() is now driven end-to-end against roundfi-core and asserts per-member USDC delta on-chain ≡ L1 net within ε = 1 USDC base unit. Pre-default / Post-default / Cascade unlock mechanically once the canary turns green organically; the matrix-driver harness already supports all four preset shapes.

Repository Layout

RoundFinancial/
├── programs/                           # Anchor programs (Rust)
│   ├── roundfi-core/                           # Pool state machine + escrow + solidarity vault
│   ├── roundfi-reputation/                     # SAS-compatible attestation + reputation ladder
│   ├── roundfi-yield-mock/                     # Devnet yield adapter (simulated APY)
│   └── roundfi-yield-kamino/                   # Mainnet yield adapter (real Kamino CPI)
├── sdk/                                # TypeScript SDK generated from Anchor IDL
├── services/orchestrator/              # Lifecycle orchestrator (mock + real driver)
├── app/                                # Next.js 14 front-end (Wallet Adapter, Phantom/Solflare/Backpack)
│   ├── src/app/                                # Routes
│   │   ├── page.tsx                            # / public landing (CoFi paradigm + Security grid + FAQ + Waitlist)
│   │   ├── home/                               # /home Bento dashboard (gated by wallet connect)
│   │   ├── carteira/                           # /carteira (4 tabs · Receive/Send/Withdraw modals · DEMO badges)
│   │   ├── grupos/                             # /grupos catalog (level gating · Novo ciclo modal)
│   │   ├── reputacao/                          # /reputacao SAS passport (copyable · Bond detail modal · level-up bridge)
│   │   ├── mercado/                            # /mercado Buy + Sell tabs (Escape Valve flow)
│   │   ├── insights/                           # /insights score curve (zooming range · Recommendation modals)
│   │   ├── lab/                                # /lab Stress Lab (L1 actuarial simulator · 5 preset scenarios)
│   │   └── demo/                               # /demo lifecycle demo (orchestrator + wallet adapter)
│   ├── src/components/                         # By feature: brand · layout · home · carteira · grupos · score · mercado · lab · insights · modals
│   ├── src/lib/                                # Theme · i18n (730+ keys PT/EN) · wallet · network · session · groups helpers
│   ├── src/data/                               # Typed mock fixtures (USER, NFT_POSITIONS, ACTIVE_GROUPS, …)
│   └── public/prototype/                       # Original design handoff bundle (legacy preview)
├── scripts/                            # Devnet deploy, airdrop, seed, stress runners
├── config/                             # Cluster configs + program-ID registry
├── tests/                              # Cross-program integration tests (Anchor + bankrun)
│   ├── parity.spec.ts                          # Rust ↔ TS constants/seeds parity (zero infra)
│   ├── economic_parity.spec.ts                 # L1 ↔ L2 economic parity (51 tests passing)
│   └── *.spec.ts                               # 27 spec files total · 300+ cases (lifecycle, edge, security, reputation, yield, events)
├── grant/                              # Superteam Agentic Engineering grant bundle (7 docs)
└── docs/                               # Architecture, module specs, deploy guides
    ├── pitch/                                  # 3-min decks (PT + EN) + long-form deck
    └── pt/                                     # Portuguese strategy docs (whitepaper + planning)

Documentation

Core

Pitch

English (strategy + technical) — full index in docs/en/

Grant bundle (Superteam · Agentic Engineering)

Portuguese (strategy + research)

Per-module READMEs land alongside each module as it ships.

Front-end

A complete Next.js 14 + TypeScript app with a public landing + 9 routes (/home, /carteira, /grupos, /reputacao, /mercado, /insights, /lab, /admin Demo Studio, /demo), real Solana wallet integration (devnet), session-orchestrated state, and a Web3-native aesthetic system (Neon palette, glassmorphism, animated counters, terminal-style activity log).

🚀 Try it now: roundfinancial.vercel.app — every push to main auto-deploys; PRs get preview URLs.

Run locally:

pnpm install
pnpm --filter @roundfi/app dev
# -> http://localhost:3000/

Routes

Route What's there
/ Public landing — animated gradient title + PT/EN toggle + interactive simulator + comparison table + CoFi paradigm + 6-card Security grid + 5-Q FAQ accordion + Waitlist form + scrolling tx-id "data stream" behind the hero. Connect Phantom CTAs redirect to /home.
/home Bento dashboard — clickable KPI cards (Balance/Yield → /carteira, Collateral → /insights) + featured round with CTAs (Pay installment / View catalog) + clickable group rows (open PayInstallmentModal) + radial SAS Passport ring + Triple Shield + live Activity feed.
/carteira 4 tabs · 5 wired modals: Receive (QR + copy address), Send (base58 validation + MAX), Withdraw (Kamino yield withdraw), Manage (per-connection inspector). PhantomFaucet (1-SOL airdrop + hosted fallback + Circle USDC). DEMO badges on Civic/Kamino/Solflare/PIX mocks. WalletChip airdrop has inline pill feedback.
/grupos ROSCA catalog with search + 5 multi-facet filters + level gating in 3 layers (locked card visual + locked-state modal + defensive joinGroup() guard). + New cycle opens NewCycleModal (eligible if Lv.3, locked otherwise).
/reputacao SAS passport — click-to-copy wallet + radial score + 50/30/10 ladder with level-up bridge to /insights + 4 SAS bonds opening BondDetailModal (attestation count, on-chain path, demo callout).
/mercado Buy + Sell tabs · Buy modal (offer summary + savings + demo callout for escape_valve_buy) · Sell modal (price slider 50–100% of face + 7-day slashing window + Whitepaper protections panel).
/insights Score evolution — range pill (1M/3M/6M/12M) that actually reshapes the curve + 5-factor breakdown + 3 clickable recommendation cards opening detail modals (Estimated Gain / Why / On-chain Signal).
/lab Stress Lab — L1 actuarial simulator. Inputs: tier · maturity · members · credit value · APY · admin fee. 4 one-click preset scenarios. Matrix editor (P/C/X/E cells with position-aware toggle). Pool-balance sparkline. Audit panel: Gross Cash + Solidarity Vault + Guarantee Fund − outstanding obligations = Net Solvency.
/demo Lifecycle orchestrator demo (developer-facing, not in user nav).

Aesthetic system

Calibrated against a "Web3 high-end" brief. The whole dashboard reads as a live system, not a banking statement.

  • Neon palette by default#06090F ground, #14F195 Solana green, #9945FF purple, #00C8FF teal accent. Soft (cream + sage) palette stays available via the dev Tweaks panel.
  • Glassmorphism on every primary cardbackdrop-filter: blur(12px) saturate(140%) over a translucent base + 1px hairline border. One helper (glassSurfaceStyle(palette)) drives every screen.
  • Terminal sidebar — uppercase JetBrains Mono labels with 0.12em tracking, glowing green active rail.
  • SOLANA_DEVNET pulse — network status chip in the top bar pulses a green dot when connected; PHANTOM_OFFLINE greys out otherwise.
  • Wallet glow — connected wallet chip runs a subtle rfi-glow halo loop; landing CTAs run bigger rfi-btn-glow-green/purple halos so every Connect button reads as the primary action immediately.
  • Animated CountUp — every hero number (balance, yield, score, KPIs) spring-animates between values when currency / language / palette flips.
  • Terminal Activity feed — live event stream from the session orchestrator rendered with > prompt + [timestamp] + op tag + amount + tx id, color-coded per row kind (in / out / attestation / join / yield).
  • Bento /home — asymmetric grid: 3 KPIs + tall radial Score ring + 3-col Featured round + balanced YourGroups / TripleShield + full-width Activity log.
  • Radial SAS Score ring — 168px SVG arc with green→teal gradient, draws in over 1.6s on first paint.
  • Page transitions — selectable via Tweaks panel: off / fade (default) / horizontal slide. Driven by framer-motion + usePathname.

Live state & interactions

  • Real wallet flow — Standard-wallet discovery via @solana/wallet-adapter-react picks up Phantom / Solflare / Backpack automatically. Connect from the landing → bounces to /home. Disconnect from the wallet chip dropdown → bounces back to /.
  • Devnet faucet — One-click 1-SOL airdrop inside the Phantom card on /carteira. Falls back to https://faucet.solana.com when the public RPC rate-limits (always-visible secondary CTA), plus https://faucet.circle.com for devnet USDC.
  • Functional modals (17) — every actionable surface across the app routes to an honest demo modal:
    • /home: PayInstallmentModal (Triple Shield breakdown), JoinGroupModal (locked branch when Lv > user.level)
    • /grupos: JoinGroupModal, NewCycleModal (eligible vs locked)
    • /mercado: BuyOfferModal (offer summary + savings), SellPositionModal (slider + Escape Valve panel), SellShareModal (legacy)
    • /carteira: ReceiveModal, SendModal (address validation + MAX), WithdrawYieldModal, ManageConnectionModal
    • /reputacao: BondDetailModal (attestation count + on-chain path)
    • /insights: RecommendationModal (3 detail variants)
    • /lab: MemberInfoModal (per-member ledger drilldown)
    • All animated via framer-motion, body-scroll locked, Esc + click-outside close. Each one names the M3 Anchor instruction it'll wire to in production via a yellow MODO DEMO callout.
  • Session orchestratorlib/session.tsx drives a typed reducer over { user, events[] }. Submitting a modal really mutates balance / score / yield. An ambient yield ticker fires every 35s so the dashboard reads as alive even while idle.
  • i18n PT/EN — Every label, button, message, and the entire landing flip on a single toggle. 650+ keys per locale (~1,300 total) in lib/i18n.tsx.
  • BRL ↔ USDC currency toggle — Source data is BRL; fmtMoney(brl) converts at runtime (USDC_RATE = 5.5).

Brand & primitives

  • RFILogoMark — pure SVG vector, gradient #27D67B → #3BC6D9 → #1E90C9. Same component drives the landing header, footer, and the /icon.svg favicon (both are vectorized — no raster fallbacks).
  • Brand kitRFIPill × 6 tones, RFICard × 4 accents, MonoLabel, 26 stroke-based icons in components/brand/.
  • Typography — Syne (display, 400–800), DM Sans (body, 400–700), JetBrains Mono (numbers, 400–600). Loaded via next/font/google and exposed as CSS variables.

Dev affordances

  • Tweaks panel (bottom-right ✨ button, dev/preview only) — flip palette, page-transition mode, and quick-jump between routes. Hidden in production.
  • Typed mock datadata/{carteira,groups,score,market,insights}.ts with full types so screens are self-contained until the on-chain indexer ships.

Development Status

PRs merged on main through #413 · all squash-merged via claude/<scope> branches with structured bodies + Claude session links.

Step Status
1. Project analysis ✅ Done
2. Architecture spec ✅ Done
3. Devnet environment ✅ Done
4. Smart contracts drafted ~8,655 LoC across the 4 in-scope Anchor programs (29 roundfi-core instructions + roundfi-reputation + roundfi-yield-kamino + roundfi-yield-mock) (lifecycle: create_pool, init_pool_vaults, join_pool, contribute, claim_payout, release_escrow, settle_default, close_pool; yield: deposit_idle_to_yield, harvest_yield; escape valve commit-reveal: escape_valve_list_commit, escape_valve_list_reveal, escape_valve_list, escape_valve_buy, cancel_pending_listing; governance timelocks: initialize_protocol, update_protocol_config, propose/cancel/commit_new_authority, propose/cancel/commit_new_fee_bps_yield, propose/cancel/commit/lock_treasury, lock_approved_yield_adapter, pause; dev: ping) + math modules + state types. Validated end-to-end on devnet across M1, M2, M3 (see row 10). 1 protocol fix shipped during M3 (mpl-core owner-managed plugin re-approval after TransferV1).
5. Contract tests 🟢 L1↔L2 economic-parity scaffold + 300+ test cases across 27 spec files (314+ counting frontend allowlist + indexer-log JSON shape + mainnet-hardening BLOCKER suite per MAINNET_READINESS.md) covering lifecycle, edge cases (cycle boundaries, degenerate shapes, grace-period defaults, shield-1-only seizure), security (CPI, inputs, audit paths, economic invariants, lifecycle), reputation (guards, CPI, lifecycle), yield integration, parity, event encoding, app-encoder structural parity (58 tests) + app-encoder bankrun round-trips (7 tests, 4 happy-path + 3 negative-path) + 10 canary-control negative tests + 36 audit-regression unit/proptest covering Critical/High remediations (SEV-001/002/021/022/024/029/031/034b/040/041/042). Plus 6 cargo-fuzz targets on roundfi-math (60s PR smoke + 30min weekly long-run; ~9.85B inputs swept cumulative — 503M historical + 600M afternoon re-validation 2026-05-24 + 8.75B overnight sweep 2026-05-24 (6 targets × 1h each: bps 1.59B / cascade 1.19B / dc_invariant 1.49B / escrow_vesting 1.58B / seed_draw 1.51B / waterfall 1.39B), 0 crashes across the entire history, coverage stable across all targets — corpus already covers full code path). The bankrun_compat shim (ADR 0007) lets cooldown-bound + time-warp-bound specs run in seconds rather than waiting 7 days of real time. All passing under bankrun + the same IDL-free SDK encoders the front-end and indexer use.
6. Backend services 🟢 SDK + indexer scaffold shipped, browser round-trip closed. @roundfi/sdk ships 7 IDL-free TS action helpers (initializeProtocol, createPool, joinPool, contribute, claimPayout, settleDefault, closePool in actions.ts) + 3 raw account decoders (Pool, Member, Listing in onchain-raw.ts) + event encoders (events.ts) + PDA derivation helpers (pda.ts), consumed by both the front-end and the indexer. services/indexer/ ships Fastify + Helius webhook + Prisma/Postgres schema (pools/members/attestations) + getProgramAccounts backfill. Round-trip proven end-to-end: PayInstallmentModal → SDK encoder → Phantom signs → devnet → Solscan tx 37FZUtg7…wg6f; ClaimPayoutModal → tx LKickMQ1…SEv7Ym. Pending: reconciler that joins event rows → canonical pool/member rows + B2B score oracle endpoint + indexer running on a hosted cluster (post-hackathon).
7. Frontend ✅ Landing + 9 routes (/home, /carteira, /grupos, /reputacao, /mercado, /insights, /lab, /admin Demo Studio, /demo) + Phantom devnet flow + 17 functional modals + Stress Lab L1 reference + Web3 aesthetic system + 6 Demo Studio presets with deterministic clean-stage iteration (synthesizes implied payment history so /insights factors and Activity feed reflect persona, no residual state between preset loads)
8. Integration 🟢 End-to-end browser → SDK → devnet round-trip closed. Phantom-signed contribute() + claim_payout() from PayInstallmentModal/ClaimPayoutModal route through @roundfi/sdk (IDL-free encoders) to devnet RPC and surface receipts in Solscan. The Receive (claim-payout) CTA covers all three group surfaces: FeaturedGroup, GroupRow, and /grupos GroupCard, plus the Demo Studio mock-mode path. /insights factors reactive to live session state (events + joinedGroups). Pending: indexer-backed reads (front-end reads on-chain directly today; B2B oracle endpoint and reconciler are post-hackathon).
9. Security audit 🟡 Internal pre-audit complete (May 2026) — formal external auditor engagement (Adevar / Halborn / OtterSec / Sec3 — selection pending) in scoping. A 5-pass red-team exercise + 1 integration-testing wave + 9 follow-up waves through #413 simulating an external auditor's methodology, run by the team before commissioning the paid auditor; 51 findings catalogued in docs/security/internal-audit-findings.md — 49 closed (Critical/High 16 of 16: 6 Critical + 10 High, including SEV-034b surfaced by integration-testing wave, SEV-040/041/042 surfaced by the Kamino-spike pre-audit wave, SEV-047 reputation-farming gate from the 2026-05-24 external-audit pass, and SEV-049 + SEV-050, the two High liveness locks from the litesvm L1↔L2 parity slice — SEV-049 = skip_defaulted_payout, SEV-050 = removed close_pool's unsatisfiable defaulted-pool guard), 0 open, SEV-012 closed via a REQUIRED litesvm CI lane, SEV-039 closed via the close_member + close_pool_vaults rent-reclaim ceremony, 2 design-intentional. Layered test coverage: 53 security-specific bankrun tests + 58 app-encoder structural + 7 bankrun round-trips + 10 canary-control negative + 36 audit-regression unit/proptest + 6 cargo-fuzz targets on roundfi-math (see audit-readiness.md TL;DR). 12 security docs indexed in docs/security/README.md: self-audit, audit-readiness, internal-audit-findings, constants-audit-2026-05, adversarial-threat-model, mev-front-running, frontend-security-checklist, indexer-threat-model, passport-bridge-threat-model, economic-config-governance, immunefi-submission-package, bug-bounty. mpl-core TransferV1 plugin-authority production bug surfaced + fixed during M3 devnet. CI runs 6 lanes — js · lint + typecheck + parity + L1 (incl. the constants floor-guard, SEV-002 follow-up), audit · cargo-audit, deny · supply-chain, anchor · build, bankrun · no-mpl-core (security_kamino_cpi), and litesvm · mpl-core path (join_pool lifecycle) (REQUIRED — closes SEV-012). SECURITY.md published for responsible disclosure; bug bounty live at mainnet GA (Immunefi/HackenProof, USD 50k initial pool — see docs/security/bug-bounty.md). This is not an external-firm attestation — it's our own pre-audit work framed in the standard issue-template shape so the formal engagement starts from a clean baseline.
10. Devnet testing 🟢 Full M3 protocol surface exercised on devnet across three pools + Escape Valve + Pool 1 finalized via close_pool (balanced summary: total_contributed=$90 = total_paid_out=$90) + Pool 3 settle_default with Triple Shield seizure on real funds. Pool 1: 3-cycle ROSCA closed + EscrowLocked negative test + close_pool. Pool 2 (cycle_duration=3600s): ON-TIME contribs + Yield Cascade + positive release_escrow + escape_valve_list + escape_valve_buy. Pool 3 (cycle_duration=60s, GRACE_PERIOD=60s devnet patch): fresh wallet set joined, slot 2 fell behind ($5 < $10 installment), claim_payout(0) advanced the cycle, settle_default(1) drained the solidarity vault ($0.20) and stopped at shield 1 because the D/C invariant already heldmember.defaulted=true, SCHEMA_DEFAULT attestation written, escrow + stake left intact. Real mpl-core bug surfaced and fixed end-to-end: TransferV1 resets owner-managed plugin authorities; fix re-approves them post-transfer. 4 Triple Shield guards captured firing on real funds (WaterfallUnderflow ×2, EscrowLocked, shield-1-only seizure). Browser-signed write loop closed end-to-end: member-3 contributes via PayInstallmentModal → tx 37FZUtg7…wg6f; member-4 receives via the new ClaimPayoutModal → tx LKickMQ1…SEv7Ym. The Receive (claim-payout) CTA also extends to Demo Studio mock mode + /grupos GroupCard so scenarios without a real wallet (Maria-as-recipient, etc.) drive the same modal through the session reducer — same protocol economics surfaced live (PROGRESSO DE PAGAMENTO + TRIPLE SHIELD GARANTIA UI panels). Phase 3 indexer scaffold also landed (Fastify + Helius webhook + Postgres event store via Prisma + getProgramAccounts backfill — wired against the same IDL-free SDK decoders the front-end uses). 10 Solana 3.x Box workarounds + 1 protocol fix shipped. Post-M3 (May 2026): bankrun_compat Connection shim landed (ADR 0007) so cooldown/time-warp-bound specs run in seconds — directly enabled the SEV-034b discovery in the integration-testing wave. Squads multisig rotation rehearsal executed on parallel devnet deployment 2026-05-16 (program-id 6WuSo1ut…7Rpn, 4 phases — propose/cancel/commit/lock — validated on-chain with audit-worthy edge cases captured; see docs/devnet-deployment.md §10).
11. Mainnet migration 🟡 Canary code controls + internal pre-audit complete; formal external auditor engagement (Adevar / Halborn / OtterSec / Sec3 — selection pending) + Squads ceremony + bug bounty pending. Code-side (this sprint): Kamino harvest CPI (#309), TVL caps per-pool + protocol-wide (#310 + #314 orphan-PDA fix), yield-adapter allowlist + lock-flag (#311 + #316), devnet/mainnet network-confusion banner (#312), Squads multisig procedure + PDA-derivation utility (#313), negative bankrun coverage on canary controls (#315), Civic→Human-Passport PoP provider migration (#317). Internal pre-audit (May 2026 — 5-pass red-team + 1 integration-testing wave + 9 follow-up waves through #413, run by the team before commissioning the formal engagement so the paid auditor's clock isn't burned on findings we can surface ourselves; 51 findings catalogued in docs/security/internal-audit-findings.md): 6 Critical, 10 High, 14 Medium, 12 Low, 9 Informational. 49 🟢 closed (Critical/High 16 of 16) in PRs #326..#413 plus the 2026-05-24 external-audit pass (SEV-047 reputation-farming cycles-gate High + SEV-048 LP-distribution earmark Medium) and the litesvm L1↔L2 parity slice (SEV-049 pre-contemplation-default liveness High, fixed via skip_defaulted_payout; SEV-050 defaulted-pool close_pool liveness High, fixed by removing the unsatisfiable defaulted-pool guard), including timelocked authority rotation (SEV-021/022 High), c-token redirect fix (SEV-001 Critical), grace-period revert (SEV-002 Critical), pool viability runtime guard (SEV-031), release_escrow partial-pay overpay regression fix with 6 negative tests (SEV-029 High), release_escrow total_escrow_deposited init bug surfaced by integration-testing wave (SEV-034b Critical, PR #360), fee_bps_yield 1-day timelock (SEV-024 follow-up), and the 3 Kamino-spike Criticals (SEV-040 KAMINO_LEND_PROGRAM_ID typo, SEV-041 CPI account list 9→12, SEV-042 mainnet-hardening byte offsets — all fixed via PR #383). 0 open — Critical/High is all-closed. SEV-012 closed — the mpl_core path (join_pool / escape_valve_buy) now runs as a REQUIRED litesvm CI lane (tests/_harness/litesvm.ts + tests/litesvm_join_pool.spec.ts, Node-24-pinned to dodge a V8-GC std::bad_alloc). 2 🔵 design-intentional (SEV-018 settle_default pause bypass, SEV-032 ReputationConfig padding exhausted). SEV-039 closed — the full rent-reclaim ceremony (close_poolclose_member × N → close_pool_vaults) drains the vaults to treasury and closes every Member PDA, the 4 vault ATAs, and the Pool PDA. External pending: Formal external auditor engagement (scoping in progress), 3-of-5 Squads multisig ceremony (hardware-wallet quorum), bug bounty live (at GA), legal counsel review (Q3 2026). See MAINNET_READINESS.md for the full checklist.

On-chain Deployments

The post-deploy register lives at docs/devnet-deployment.md — that's where program IDs, tx signatures, deployer keypair, and the verification checklist are recorded. The tables below mirror the headline IDs so reviewers can hop straight to Solscan from the README.

Status: _FILL_ME_ placeholders below are intentional — they get filled in the same commit as the actual deploy, so the register exists pre-deploy and the diff is auditable in one PR.

Devnet (?cluster=devnet)

Program Program ID Status Solscan
roundfi-core 8LVrgxKwKwqjcdq7rUUwWY2zPNk8anpo2JsaR9jTQQjw ✅ deployed · 🔐 attested view
roundfi-reputation Hpo174C6JTCfiZ6r8VYVQdKxo3LBHaJmMbkgrEkxe9R2 ✅ deployed · 🔐 attested view
roundfi-yield-kamino 74izMa4WzLuHvtzDLdNzcyygKe5fYwtD95EiWMuzhFdb ✅ deployed · 🔐 attested view
roundfi-yield-mock GPTMPgxexhwkhXNovnfrcSsmoWPUhedvKAQfTV2Ef5AQ ✅ deployed · 🔐 attested view

🔐 Reproducible build, attested on-chain. Every byte at the program addresses above is bound to commit 5f1673b of this repo via an OtterSec verify-build attestation PDA on devnet. Bytecode is reproducible from source: rebuilding inside the official solanafoundation/solana-verifiable-build:1.18.26 Docker image produces a .so whose hash matches the deployed program account. Audit yourself in 30 seconds:

solana-verify -u https://api.devnet.solana.com get-program-pda \
  --program-id 8LVrgxKwKwqjcdq7rUUwWY2zPNk8anpo2JsaR9jTQQjw \
  --signer 64XM177Vm6zirzQnjU1juQ9TLqDsZVsCcZzfgEgVCffm

Returns the bound git_url + commit + executable_hash. Compare against solana-verify -u devnet get-program-hash <pid> (deployed bytecode) and solana-verify get-executable-hash target/deploy/<prog>.so (your local rebuild) — all three match. Full flow including the Docker build + redeploy step: docs/verified-build.md.

The green "Verified Build" tile on Solscan is gated on OtterSec's remote build queue, which is mainnet-only by design — out of scope while RoundFi runs on devnet. The on-chain attestation here gives the same hash-binding guarantee, just CLI-checked instead of UI-rendered.

Initialize + seed txs:

  • initialize_protocol3gCY7M…fXNUz · ProtocolConfig PDA = 3c9MmoM…vJoTMV

  • initialize_reputation59Sgz1…ALCn1 · ReputationConfig PDA = 7RDWsSDc…aXo4

  • create_pool2Emh1s…E8urS · Pool PDA = 5APoECXz…c8ooa (demo, 3 members, $30 credit slot, 3 cycles)

  • init_pool_vaultszmnoex…umnx (4 USDC vault ATAs: pool/escrow/solidarity/yield)

  • join_pool × 3 — Lv1 stakes ($15 each, 50% of credit) deposited to the escrow vault, Metaplex Core position NFTs minted with FreezeDelegate + TransferDelegate plugins:

  • contribute × 3 — cycle 0 fully paid; each $10 installment split across solidarity (1%) / escrow (25%) / pool float (74%); each call also init's a reputation Attestation PDA (SCHEMA_LATE = 2):

  • claim_payout cycle 0 / slot 0 — Pool PDA signs $30 USDC transfer to member 0, pool.current_cycle advances 0 → 1, Member.paid_out=true, SCHEMA_CYCLE_COMPLETE attestation minted:

    • Pool float top-up 4dEaTvFr…pKpe8 — deployer adds $7.80 USDC to pool_usdc_vault (proxy for the Yield Cascade LP-distribution flow that bridges this gap in production)
    • Claim tx 5fx4VLEt…qpab — member 0 USDC ATA: 15 → 45 (+$30 received)
  • contribute cycle 1 × 3 — same split, member balances rolled forward; new SCHEMA_LATE attestations:

  • claim_payout cycle 1 / slot 1 — member 1 receives $30, pool.current_cycle advances 1 → 2:

  • contribute cycle 2 × 3 — final cycle's contributions:

  • claim_payout cycle 2 / slot 2 — member 2 receives $30, pool.status = Completed:

  • release_escrow negative test (member 0, checkpoint 1) — failed on-chain with EscrowLocked code 6011 because member.on_time_count (0) < args.checkpoint (1). The protocol refused to release the legitimate $22.50 escrow balance because all contributions had been LATE. Durable on-chain enforcement evidence:

    • Failed tx 4wB8RqiP…f5Mn — log: AnchorError ... release_escrow.rs:91. Error Code: EscrowLocked. Error Number: 6011

Full ROSCA closed end-to-end on devnet, plus Triple Shield enforcement verified. Protocol init → pool create → vault inits → 3 members joined with USDC stakes + position NFTs → 9 contributions across 3 cycles → 3 payouts (slots 0 → 1 → 2) → Pool.status = Completed → 12 reputation attestations on-chain → 2 deterministic guards captured firing (WaterfallUnderflow if pool float can't cover credit; EscrowLocked if member paid late). See docs/status.md and docs/devnet-deployment.md.

Pool 2 — yield + positive release (?cluster=devnet)

Pool 2 (8XZxRSqU…twbujm, cycle_duration = 3600s) was driven specifically to exercise the M3 instructions that pool 1's late-paying lifecycle skipped: deposit_idle_to_yield + harvest_yield (the full PDF-canonical Yield Cascade) and the positive-path release_escrow (vesting math returns stake to a member who paid on-time).

  • deposit_idle_to_yield × 2 + pre-fund — 10 USDC moved from pool float to yield_mock vault, plus a 0.5 USDC pre-fund to simulate accrued APY:
  • harvest_yield — realized 0.5 USDC, full waterfall (protocol fee 20% → treasury, GF/LP/participants logical earmarks accrued):
  • release_escrow POSITIVE — member 0 received 5 USDC of vested stake (stake_deposited / cycles_total = $15 / 3):
    • 5BvLSatc…HVQm · escrow_balance: 17.50 → 12.50, last_released_checkpoint: 0 → 1, member ATA: 0 → 5 USDC

Pool 2 — Escape Valve secondary market

The protocol's differentiator vs WeTrust / RociFi: distressed members can sell their position to a buyer who picks up the obligations, instead of defaulting and triggering Triple Shield seizure.

  • List: member 1 (slot 1) listed at $14 USDC (slight discount vs $15 stake) 4aFv9zbC…tzDu · listing PDA 5sQBMvMY…oMB5A
  • Bug surfaced + fixed in flight: first buy attempt reverted with mpl-core 0x1a because TransferV1 resets owner-managed plugin authorities (FreezeDelegate / TransferDelegate). Bankrun harness only had defense-in-depth AssetNotRefrozen guards; the positive flow had never run on real mpl-core. Fix shipped: re-approve both plugins back to position_authority post-transfer. Core upgrade 2RSZQLtq…36tQ
  • Buy POSITIVE: a fresh buyer wallet picked up the listing. $14 USDC buyer→seller, atomic re-anchor closed the old Member PDA + minted a new one at the buyer's key (all bookkeeping carried over), NFT thawed/transferred/re-delegated/re-frozen under position_authority, listing closed. Buy tx 3cdG3bWR…cgCpr · new Member PDA Am3iA2sd…oxQF

Pool 3 — settle_default + Triple Shield seizure (?cluster=devnet)

Pool 3 (D9PS7Q…pDE5, cycle_duration=60s) was provisioned with a fresh wallet set (MEMBER_INDEX_OFFSET=3member-3/4/5) so neither Pool 1 nor Pool 2's existing SCHEMA_CYCLE_COMPLETE attestations interfered with the default flow's SCHEMA_DEFAULT (id=3) write. Combined with the devnet-only GRACE_PERIOD_SECS=60 patch (was 7d in production), the grace-elapsed precondition was reachable in a single test run.

  • contribute cycle 0 — slots 0+1 paid LATE (now > pool.next_cycle_at + 60s), slot 2 was SKIPPED by seed-cycle.ts pre-flight ATA balance check ($5 < $10 installment) so member-5 became the deliberate defaulter:
  • claim_payout cycle 0 / slot 0 — deployer floated $15.20 to cover slot-2's missing contribution; member-3 received $30; pool.current_cycle advances 0 → 1:
  • settle_default(1) slot 2 — Triple Shield waterfall fired: drained $0.20 from solidarity vault, stopped at shield 1 because the D/C invariant already held (c_after $30 ≥ d_rem $30), member.defaulted=true, SCHEMA_DEFAULT attestation written, escrow + stake left intact.

On-chain msg! summary captured verbatim:

roundfi-core: settle_default cycle=1 member=4sLSCzCJnZFMtaLD6vQsgZ4ywAwYa6joExK9dcM2HvKq
  seized_total = 200_000   (= $0.20)
  solidarity   = 200_000   (= $0.20)   ← drained
  escrow       = 0                       ← intact
  stake        = 0                       ← intact
  d_rem = c_init = c_after = 30_000_000  (= $30 = pool.credit_amount)

This is the first capture of the shield-1-only quadrant on real funds. The opposite extreme — installment > stake_initial + escrow_so_far — would force shields 2+3 to fire and is covered by bankrun's tests/security_default.spec.ts.

Full M3 protocol surface exercised on-chain across three pools, plus the first browser-signed write loop end-to-end. Across pool 1 (negative paths + claims + close_pool), pool 2 (yield + positive release + Escape Valve), and pool 3 (settle_default + Triple Shield seizure + browser contribute + browser claim_payout), every active M3 instruction now has a real on-chain receipt: create_pool, init_pool_vaults, join_pool, contribute, claim_payout, release_escrow, deposit_idle_to_yield, harvest_yield, escape_valve_list, escape_valve_buy, close_pool, settle_default, plus roundfi_yield_mock.init_vault. 4 Triple Shield guards captured firing on real funds (WaterfallUnderflow ×2, EscrowLocked, shield-1-only seizure). Browser-signed contribute() + claim_payout() (Phantom → IDL-free encoders → devnet) close the wiring loop — txs 37FZUtg7…wg6f (pay) + LKickMQ1…SEv7Ym (receive). An mpl-core owner-managed plugin gotcha (a real production-relevant issue bankrun missed) was surfaced and fixed end-to-end on devnet. Pool 1's close_pool emitted a balanced summary log (total_contributed=$90, total_paid_out=$90) — the lifecycle invariant for a completed ROSCA holds. 16 reputation Attestation PDAs on-chain (13 cycle + 1 SCHEMA_DEFAULT + 1 SCHEMA_LATE from browser contribute + 1 SCHEMA_CYCLE_COMPLETE from browser claim). 10 Solana 3.x Box workarounds + 1 protocol fix shipped this milestone.

App ↔ chain wiring foundation

The front-end's read path is now wired against the deployed pools (foundation on branch claude/m3-app-wiring-foundation):

  • IDL-free pool + member decoders in sdk/src/onchain-raw.ts (Anchor's IDL gen is broken on Rust 1.95+; we replicate the offsets from pool.rs / member.rs byte-for-byte). React hooks usePool(seedKey) and usePoolMembers(seedKey) poll every 30s.
  • /home lights up live — the FeaturedGroup card overrides its mock counters with real Pool 2 state (members joined / cycle / installment / credit) when devnet RPC responds, plus a "ROSTER" chip row beneath the avatars showing the three real wallets with slot tags + on-time / contributions tooltips + red border on defaulted=true. A new <DevnetPoolStatus /> row shows all 3 deployed pools side-by-side with status badge + live counters + Solscan links per card.
  • /grupos — the catalog now opts cards into an "on-chain · devnet" pill (linked to Solscan) via an optional devnetPool field on the fixture. g1 is tagged → pool 3. When a fixture is also flagged contemplated: true (Demo Studio scenarios), the GroupCard's primary CTA flips to a purple-teal "Receber R$ X" button (literal PT UI label rendered by the app's i18n layer when PT locale is active).
  • Three IDL-free write encoders all under app/src/lib/:
    • contribute.ts — discriminator 522144832000cd5f, 18 accounts (validated end-to-end on devnet)
    • claim-payout.ts — discriminator 7ff0843ee3c69285, 14 accounts (validated end-to-end on devnet)
    • escape-valve-buy.ts — discriminator c48acf6a712d9c54, 15 accounts + 5 mpl-core CPIs at 600k CU (encoder shipped, UI wire deferred)
  • PayInstallmentModal + ClaimPayoutModal auto-detect on-chain mode when the connected wallet is a materialized member of the target pool, swap the mock 1500ms timeout for a real wallet.sendTransaction, render tx hash + Solscan link on success. Both modals surface the protocol economics inline: a Payment Progress grid (installments paid / remaining / outstanding debt — labeled PROGRESSO DE PAGAMENTO in the PT UI) + a Triple Shield Collateral grid (stake locked + escrow accumulated + total collateral — labeled TRIPLE SHIELD GARANTIA in the PT UI) so the demo answers the natural "is the user really receiving 100% of credit_amount upfront, regardless of level / installments paid?" question on screen.
  • Demo Studio + /grupos mock-mode CTA — the same ClaimPayoutModal is now dual-mode. Chain mode fires the real claim_payout tx; mock mode (when memberRecord/pool/seedKey props are omitted) drives the session.claimPayoutMock reducer for Demo Studio scenarios where the contemplated user has no on-chain wallet match. Same UX, same protocol disclosure, different ingress.

Read paths degrade gracefully (status="fallback" → muted "rpc unavailable" line) and the write path falls back to the mock confirm when pre-conditions don't hold, so the localhost demo / unconnected-wallet flow stays unchanged.

Write loop validated end-to-end on devnet (2026-05-07). TWO browser-signed txs, opposite sides of the ROSCA cycle:

  • Pay — Member-3 imported into Phantom, connected on /home, FeaturedGroup flipped to ON-CHAIN · DEVNET reading Pool 3 live, PayInstallmentModal showed the green ON-CHAIN banner, user signed in Phantom, the IDL-free encoder dispatched contribute(cycle=1, schemaId=SCHEMA_LATE) and the program landed it cleanly. Tx 37FZUtg7…wg6f — first browser-signed contribute() in RoundFi history. Member-3's USDC ATA dropped 45 → 35.
  • Receive — Member-4 imported via the new pnpm devnet:export-pk helper, connected on /home. FeaturedGroup detected member.slot_index == pool.current_cycle == 1 and surfaced the new purple-teal claim-payout CTA (rendered as "Receber R$ 165" under PT locale) next to the pay-installment CTA ("Pagar parcela"). Click → ClaimPayoutModal showed the ON-CHAIN banner with claim_payout(cycle=1) + four-bullet state transition preview. First attempt reverted with WaterfallUnderflow (pool float $7.60 < credit_amount $30) — the protocol's solvency guard working as designed, captured live. The new pnpm devnet:seed-topup companion script computed the gap (credit − spendable + cushion) and bridged it from the deployer (tx 3iFuuEwP…s9VQ). Retry landed claim_payout tx LKickMQ1…SEv7Ym. Member-4's USDC ATA: 35 → 65, pool.current_cycle 1 → 2, member.paid_out=true, SCHEMA_CYCLE_COMPLETE attestation written.

Both write paths use the same byte-for-byte IDL-free encoder methodology (precomputed Anchor discriminator + manual account list mirroring the program's <Accounts> declaration). The remaining escape_valve_buy encoder (also shipped in this PR) inherits the same confidence even before its own end-to-end run.

Mainnet (smoke deploy — presence only, not initialized for live users)

The Mainnet IDs below validate the CD pipeline against real-cluster conditions and give reviewers a clickable Mainnet Solscan link as evidence of execution. The protocol is not initialized; production launch is gated behind the Phase 3 milestone in docs/status.md. Procedure: docs/devnet-deployment.md §8.

Program Program ID Solscan
roundfi-core _FILL_ME_ view
roundfi-reputation _FILL_ME_ view
roundfi-yield-mock _FILL_ME_ view
roundfi-yield-kamino _FILL_ME_ view

Deploy tx (any of the four uploads): _FILL_ME_ (view)

Stack

Layer Tech
Smart contracts Rust + Anchor 0.30
Tests anchor test + solana-bankrun
NFTs Metaplex Core
NFT metadata Client-supplied URI today (https:// / ipfs:// / ar:// accepted); Arweave-via-Irys upload pipeline planned post-mainnet — IRYS_NODE_URL already wired in config/clusters.ts
Attestations In-house SAS-compatible module (Devnet) → official SAS (Mainnet)
Yield Mock adapter (Devnet) → Kamino CPI (Mainnet). roundfi-yield-kamino::deposit() does a real deposit_reserve_liquidity CPI on Kamino Lend mainnet program; the harvest CPI has shipped — harvest() does a real redeem_reserve_collateral (redeem-all + redeposit-principal round-trip).
Stablecoin USDC
Backend Node.js + TypeScript + Fastify + Prisma + PostgreSQL — indexer scaffold landed in M3 (services/indexer/: webhook handler + IDL-free Anchor log decoder + getProgramAccounts backfill against the same SDK helpers the front-end uses); see services/indexer/README.md for run instructions and docs/architecture.md for design
Frontend Next.js 14 + React 18 + framer-motion 11 + Tailwind 3 (landing) + @solana/wallet-adapter + @coral-xyz/anchor
Cluster Devnet → Mainnet (env-driven)

Quick Start

Run the front-end (no on-chain deploy needed)

git clone https://github.com/alrimarleskovar/RoundFinancial.git
cd RoundFinancial
pnpm install
pnpm --filter @roundfi/app dev
# -> http://localhost:3000/

To use the live wallet flow on devnet, install Phantom and switch its network to Devnet before clicking "Connect Wallet".

Deploy programs to devnet

See docs/devnet-setup.md for the full walkthrough. Short version (WSL2 / Linux / macOS):

cp .env.example .env
solana config set --url https://api.devnet.solana.com
mkdir -p keypairs && solana-keygen new -o keypairs/deployer.json
export ANCHOR_WALLET=$(pwd)/keypairs/deployer.json

pnpm run devnet:airdrop           # 2 SOL (repeat as needed)
pnpm run devnet:deploy            # build → keys sync → build → deploy
# copy the printed IDs into .env

All 20 roundfi-core instructions are deployed and exercised on devnet (see On-chain Deployments). The ping dev-only smoke instruction stays in the program as a quick connectivity check.

Deploy the front-end (Vercel)

The repo ships an app/vercel.json so the deploy works with one tweak in the dashboard:

  1. Sign in at vercel.comAdd NewProject → import alrimarleskovar/RoundFinancial.
  2. Set Root Directory to app (this is the only manual step — Vercel needs to find next in app/package.json, not the workspace root).
  3. Leave everything else at the default. Vercel reads app/vercel.json and:
    • Runs cd .. && pnpm install --frozen-lockfile so the pnpm workspace resolves (@roundfi/sdk, @roundfi/orchestrator).
    • Builds the app: pnpm build inside app/.
    • Auto-detects Next.js inside app/ and applies all framework optimizations.
  4. Click Deploy. ~2 minutes.

No env vars required for the public landing — wallet adapter handles its own RPC defaults (devnet). For browser-signed write paths against devnet (now live), the deploy uses:

  • NEXT_PUBLIC_SOLANA_RPC_URL (Helius / public devnet)
  • NEXT_PUBLIC_ROUNDFI_CORE_PROGRAM_ID
  • NEXT_PUBLIC_ROUNDFI_REPUTATION_PROGRAM_ID

The ignoreCommand in app/vercel.json skips rebuilds when only docs/grant/programs/tests change — saves build minutes on doc-only PRs.

License

Apache-2.0 — full text in LICENSE. Covers the four Anchor programs (programs/roundfi-core, roundfi-reputation, roundfi-yield-mock, roundfi-yield-kamino), the IDL-free SDK (sdk/), and the Next.js app (app/). Reputation scoring methodology is documented openly in docs/en/04-behavioral-reputation-score.pdf so any third party can audit how the score is generated. A future hosted B2B scoring service (Phase 3) may ship under a separate license; not yet released.

Links

About

RoundFi — behavioral-credit infrastructure for Solana. ROSCAs as data engine, on-chain reputation as product.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors