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.
🚀 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.
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-reputationprogram +tests/reputation_cpi.spec.ts). On the user-facing side, the/reputacaosurface 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.rsand 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.
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_payoutinstruction, SEV-050 by removingclose_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_accountinroundfi-yield-kamino::Depositcould redirect Kamino c-tokens to an attacker ATA. Closed by #326 withassociated_token::mint+associated_token::authorityconstraint pinning the protocol-owned ATA. - SEV-002 (Critical):
GRACE_PERIOD_SECS = 60devnet 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_payoutCPI flows through the back door (#337). - SEV-024 follow-up: 1-day timelock pilot on
fee_bps_yield(#347). Direct mutation viaupdate_protocol_confignow returnsDirectFeeBpsYieldMutationDisabled— 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 usingcumulative_paid = stake - escrow_balanceand 6 negative regression tests (4 unit + 2 proptest invariants) per the new "negative test before merge" gate. - SEV-031 (Low):
create_poolnow 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_defaultcascade math refactored to delegate toroundfi_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).
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.
- 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_000credit 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:
- Seed Draw — Month-1 retention of 91.6% of capital.
- Adaptive Escrow — locks reward portions so debt decreases faster than collateral returns.
- 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) inprograms/roundfi-yield-kamino. Devnet uses the mock adapter (programs/roundfi-yield-mock) for deterministic test cycles; mainnet flips to the kamino adapter via theconfig.approved_yield_adapterallowlist. Adapter is swap-via-Pool.yield_adapterPubkey — 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".
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.
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)
Core
- Architecture Spec — programs, accounts, instructions, PDAs, CPI graph, error taxonomy
- Devnet Setup — full prerequisites + deploy walkthrough
- Pitch Alignment — how the implementation maps to the deck
- Yield & Guarantee Fund — waterfall math + adapters
Pitch
- 3-min Pitch · EN — 12-slide short-form deck (English)
- 3-min Pitch · PT — 12-slide short-form deck (Portuguese)
- Long-form Deck · EN — 15-slide Colosseum deck
English (strategy + technical) — full index in docs/en/
- 00 · Documentation Index — formal strategic index of the package
- 01 · Overview — entry point, 60-second pitch in document form
- 02 · Technical Whitepaper — protocol whitepaper, source of truth for mechanics
- 03 · Architecture Spec — program topology, account model, instruction surface
- 04 · Behavioral Reputation Score — 50/30/10 ladder + attestation schemas
- 05 · Stress Lab & Economic Model — L1 actuarial simulator + Triple Shield invariants
- 06 · Market & GTM — market sizing + ICP + go-to-market motion
- 07 · Business Model & B2B Oracle — 3-phase revenue + Phase 3 endgame
- 08 · Competitive Analysis — honest positioning vs Aave, Kamino, Maple, TrueFi, Goldfinch, Credix, RociFi, ARCx, WeTrust
- 09 · Risk & Compliance — risk taxonomy + regulatory framing + compliance posture
- 10 · User Guide — end-user onboarding, step by step
- 11 · Devnet Status & Proof — Solscan receipts + Triple Shield enforcement evidence
Grant bundle (Superteam · Agentic Engineering)
- Grant index — 7-file response bundle
- Project overview · Agentic process · PR log
- Grant use · Builder note · Milestones
Portuguese (strategy + research)
- Whitepaper Técnico
- Guia do Usuário
- Viabilidade Técnica
- Escada de Reputação
- Válvula de Escape
- Plano Estratégico B2B
- Plano de Expansão
Per-module READMEs land alongside each module as it ships.
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
mainauto-deploys; PRs get preview URLs.
Run locally:
pnpm install
pnpm --filter @roundfi/app dev
# -> http://localhost:3000/| 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). |
Calibrated against a "Web3 high-end" brief. The whole dashboard reads as a live system, not a banking statement.
- Neon palette by default —
#06090Fground,#14F195Solana green,#9945FFpurple,#00C8FFteal accent. Soft (cream + sage) palette stays available via the dev Tweaks panel. - Glassmorphism on every primary card —
backdrop-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_OFFLINEgreys out otherwise. - Wallet glow — connected wallet chip runs a subtle
rfi-glowhalo loop; landing CTAs run biggerrfi-btn-glow-green/purplehalos 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.
- Real wallet flow — Standard-wallet discovery via
@solana/wallet-adapter-reactpicks 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 DEMOcallout.
- Session orchestrator —
lib/session.tsxdrives 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).
RFILogoMark— pure SVG vector, gradient#27D67B → #3BC6D9 → #1E90C9. Same component drives the landing header, footer, and the/icon.svgfavicon (both are vectorized — no raster fallbacks).- Brand kit —
RFIPill× 6 tones,RFICard× 4 accents,MonoLabel, 26 stroke-based icons incomponents/brand/. - Typography — Syne (display, 400–800), DM Sans (body, 400–700), JetBrains Mono (numbers, 400–600). Loaded via
next/font/googleand exposed as CSS variables.
- Tweaks panel (bottom-right ✨ button, dev/preview only) — flip palette, page-transition mode, and quick-jump between routes. Hidden in production.
- Typed mock data —
data/{carteira,groups,score,market,insights}.tswith full types so screens are self-contained until the on-chain indexer ships.
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 held — member.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_pool → close_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. |
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.
| 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
5f1673bof this repo via an OtterSec verify-build attestation PDA on devnet. Bytecode is reproducible from source: rebuilding inside the officialsolanafoundation/solana-verifiable-build:1.18.26Docker image produces a.sowhose 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 64XM177Vm6zirzQnjU1juQ9TLqDsZVsCcZzfgEgVCffmReturns the bound
git_url+commit+executable_hash. Compare againstsolana-verify -u devnet get-program-hash <pid>(deployed bytecode) andsolana-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_protocol→3gCY7M…fXNUz· ProtocolConfig PDA =3c9MmoM…vJoTMV -
initialize_reputation→59Sgz1…ALCn1· ReputationConfig PDA =7RDWsSDc…aXo4 -
create_pool→2Emh1s…E8urS· Pool PDA =5APoECXz…c8ooa(demo, 3 members, $30 credit slot, 3 cycles) -
init_pool_vaults→zmnoex…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:- Member 0 →
4r2Pd9qv…ADc5· join tx2UrRDG…dnLD - Member 1 →
3Sr4M88H…eEnm· join tx3GJUTi…wU8k - Member 2 →
6ymEiWiA…cYiaa· join tx3L7dtn…ceYSJ
- Member 0 →
-
contribute× 3 — cycle 0 fully paid; each $10 installment split across solidarity (1%) / escrow (25%) / pool float (74%); each call also init's a reputationAttestationPDA (SCHEMA_LATE = 2):- Member 0 cycle 0 →
ysSSQJh…6HHW - Member 1 cycle 0 →
3MwScoes…cMYJ - Member 2 cycle 0 →
yTVakGw…iDT
- Member 0 cycle 0 →
-
claim_payoutcycle 0 / slot 0 — Pool PDA signs $30 USDC transfer to member 0,pool.current_cycleadvances 0 → 1,Member.paid_out=true,SCHEMA_CYCLE_COMPLETEattestation minted:- Pool float top-up
4dEaTvFr…pKpe8— deployer adds $7.80 USDC topool_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)
- Pool float top-up
-
contributecycle 1 × 3 — same split, member balances rolled forward; new SCHEMA_LATE attestations:- Member 0 cycle 1 →
3hqMZGB…JGBdB - Member 1 cycle 1 →
CFt7rHW…BeY9G - Member 2 cycle 1 →
P3iaunv…sGRmM
- Member 0 cycle 1 →
-
claim_payoutcycle 1 / slot 1 — member 1 receives $30,pool.current_cycleadvances 1 → 2:- Top-up
HwC3ZGd…gWgD· Claim tx4KEmjib…ye1o— member 1 USDC ATA: 5 → 35
- Top-up
-
contributecycle 2 × 3 — final cycle's contributions:- Member 0 cycle 2 →
4T1W7cB…61mJ8 - Member 1 cycle 2 →
5PHr9Qn…sfsQ - Member 2 cycle 2 →
3AQ3jxv…6VvQj
- Member 0 cycle 2 →
-
claim_payoutcycle 2 / slot 2 — member 2 receives $30,pool.status = Completed:- Top-up
4MgZk1C…kZJHH· Claim tx4bjda3t…Kfwc— member 2 USDC ATA: 15 → 45
- Top-up
-
release_escrownegative test (member 0, checkpoint 1) — failed on-chain withEscrowLockedcode 6011 becausemember.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
- Failed tx
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 (WaterfallUnderflowif pool float can't cover credit;EscrowLockedif member paid late). Seedocs/status.mdanddocs/devnet-deployment.md.
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:- Last deposit
3gAbmM48…U3kp· pre-fund26DN91xo…3gf2
- Last deposit
harvest_yield— realized 0.5 USDC, full waterfall (protocol fee 20% → treasury, GF/LP/participants logical earmarks accrued):U1vK5GXM…sdmq· pool float +0.4, treasury +0.1
release_escrowPOSITIVE — 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
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 PDA5sQBMvMY…oMB5A - Bug surfaced + fixed in flight: first buy attempt reverted with mpl-core
0x1abecauseTransferV1resets owner-managed plugin authorities (FreezeDelegate / TransferDelegate). Bankrun harness only had defense-in-depthAssetNotRefrozenguards; the positive flow had never run on real mpl-core. Fix shipped: re-approve both plugins back toposition_authoritypost-transfer. Core upgrade2RSZQLtq…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 tx3cdG3bWR…cgCpr· new Member PDAAm3iA2sd…oxQF
Pool 3 (D9PS7Q…pDE5, cycle_duration=60s) was provisioned with a fresh wallet set (MEMBER_INDEX_OFFSET=3 → member-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.
contributecycle 0 — slots 0+1 paid LATE (now > pool.next_cycle_at + 60s), slot 2 was SKIPPED byseed-cycle.tspre-flight ATA balance check ($5 < $10 installment) so member-5 became the deliberate defaulter:- Member-3 cycle 0 →
HWeuu9J8…61WEy - Member-4 cycle 0 →
5YhGNfHY…g3auz
- Member-3 cycle 0 →
claim_payoutcycle 0 / slot 0 — deployer floated $15.20 to cover slot-2's missing contribution; member-3 received $30;pool.current_cycleadvances 0 → 1:- Top-up
532qSPCE…xAMsD· Claim tx4DEb5AQo…re7GD
- Top-up
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.- Settle tx
34UyAtEP…NeJeG· Member-2 PDA (nowdefaulted=true)GqzmPkW7…SqfHQ
- Settle tx
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, plusroundfi_yield_mock.init_vault. 4 Triple Shield guards captured firing on real funds (WaterfallUnderflow×2,EscrowLocked, shield-1-only seizure). Browser-signedcontribute()+claim_payout()(Phantom → IDL-free encoders → devnet) close the wiring loop — txs37FZUtg7…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 reputationAttestationPDAs 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.
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 frompool.rs/member.rsbyte-for-byte). React hooksusePool(seedKey)andusePoolMembers(seedKey)poll every 30s. /homelights 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 ondefaulted=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 optionaldevnetPoolfield on the fixture.g1is tagged → pool 3. When a fixture is also flaggedcontemplated: 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— discriminator522144832000cd5f, 18 accounts (validated end-to-end on devnet)claim-payout.ts— discriminator7ff0843ee3c69285, 14 accounts (validated end-to-end on devnet)escape-valve-buy.ts— discriminatorc48acf6a712d9c54, 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 — labeledPROGRESSO DE PAGAMENTOin the PT UI) + a Triple Shield Collateral grid (stake locked + escrow accumulated + total collateral — labeledTRIPLE SHIELD GARANTIAin 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 +
/gruposmock-mode CTA — the sameClaimPayoutModalis now dual-mode. Chain mode fires the realclaim_payouttx; mock mode (when memberRecord/pool/seedKey props are omitted) drives thesession.claimPayoutMockreducer 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,PayInstallmentModalshowed the green ON-CHAIN banner, user signed in Phantom, the IDL-free encoder dispatchedcontribute(cycle=1, schemaId=SCHEMA_LATE)and the program landed it cleanly. Tx37FZUtg7…wg6f— first browser-signedcontribute()in RoundFi history. Member-3's USDC ATA dropped 45 → 35.- Receive — Member-4 imported via the new
pnpm devnet:export-pkhelper, connected on/home. FeaturedGroup detectedmember.slot_index == pool.current_cycle == 1and 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 →ClaimPayoutModalshowed the ON-CHAIN banner withclaim_payout(cycle=1)+ four-bullet state transition preview. First attempt reverted withWaterfallUnderflow(pool float $7.60 < credit_amount $30) — the protocol's solvency guard working as designed, captured live. The newpnpm devnet:seed-topupcompanion script computed the gap (credit − spendable + cushion) and bridged it from the deployer (tx3iFuuEwP…s9VQ). Retry landed claim_payout txLKickMQ1…SEv7Ym. Member-4's USDC ATA: 35 → 65,pool.current_cycle1 → 2,member.paid_out=true,SCHEMA_CYCLE_COMPLETEattestation 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 remainingescape_valve_buyencoder (also shipped in this PR) inherits the same confidence even before its own end-to-end run.
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)
| 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) |
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".
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 .envAll 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.
The repo ships an app/vercel.json so the deploy works with one tweak in the dashboard:
- Sign in at vercel.com → Add New → Project → import
alrimarleskovar/RoundFinancial. - Set Root Directory to
app(this is the only manual step — Vercel needs to findnextinapp/package.json, not the workspace root). - Leave everything else at the default. Vercel reads
app/vercel.jsonand:- Runs
cd .. && pnpm install --frozen-lockfileso the pnpm workspace resolves (@roundfi/sdk,@roundfi/orchestrator). - Builds the app:
pnpm buildinsideapp/. - Auto-detects Next.js inside
app/and applies all framework optimizations.
- Runs
- 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_IDNEXT_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.
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.
- Repo: https://github.com/alrimarleskovar/RoundFinancial
- Hackathon: Colosseum 2026