Skip to content

Investment Lifecycle

End-to-end investment flow: Deposit → LP Mint → Active → Yield → Redemption. Pool-specific details in Pool Models.

Roles: 🔵 Investor · 🟢 System (Auto) · 🟠 Operator · 🔴 Admin · 🟣 Fund Issuer

Phase 1 — Deposit

① Investor connects wallet & passes KYC 🔵 Investor

SumSub KYC → SBT (Soulbound Token — non-transferable on-chain credential) minted on-chain → kyc_status = APPROVED

② Investor selects pool, chooses stablecoin & enters amount 🔵 Investor

System checks: is_paused = false, kyc_status = APPROVED. NAV model keeps investment open during writedowns — no auto-block. If pool accepts multiple stablecoins (e.g., USDC + USDT), investor selects which to use. If only one accepted, auto-selected. See Pool Models — Accepted Stablecoins.

③ Stablecoin transferred to Pool / Escrow contract 🟢 System

AS_POOL: Selected stablecoin (USDC/USDT/DAI) → PlatformPool (100%). LP auto-minted, no receipt token. FUND_POOL: Selected stablecoin → PlatformEscrow. receipt_tx_hash recorded in deposits table. deposits.currency records which stablecoin was used.

④ Receipt Token (ERC-721) minted to investor 🟢 System ⚠️ FUND_POOL ONLY

receipt_token_id stored → status = PENDING. AS_POOL skips this step (LP auto-minted on deposit).

⑤ Refund timer starts 🟢 System ⚠️ FUND_POOL ONLY

refund_eligible_at = deposit time + 7 days. If LP not issued by then, auto-refund triggers. AS_POOL: safety net only (auto-mint is instant).

⑥ NAV snapshot stored 🟢 System 🟡 BD3

tokens_minted = stablecoin_amount / nav_per_token — LP tokens issued at fair current NAV price. nav_at_investment snapshot stored. LP issuance diverges by pool type (FUND_ISSUED / PLATFORM_ISSUED) below.

📋 Pool Model Details

Deposit flows diverge by pool type after Step ⑥. For the full breakdown including LP issuance comparison, fund flow architecture, yield settings, and reserve split logic:

View Pool Models section

Phase 2 — Yield (Claim-Based Only)

📈 Yield Flow

All yield is claim-based (MANUAL_CLAIM). Fund/FM deposits yield USDC into Pool Smart Contract → system tags per investor (pro-rata by LP) → investor calls claimYield() (USDC to wallet) or reinvest(fullYield) → new LP minted (lockup exempt). Investor pays gas, not the fund. V1: full amount only, same-pool only. allow_rollover: editable in ACTIVE state (admin toggle).

Overdue tracking: next_yield_due = last distribution + frequency. If overdue → yield_overdue = true → alert Admin + Investors. yield_frequency is a public commitment visible to investors.

Full yield settings & flow in Pool Models

Reinvest V1 Policy 🟡 BD5

🔄 Reinvest Overview

allow_rollover = true인 pool에서 투자자가 yield를 동일 pool에 재투자할 수 있음.

핵심 규칙:

  • 전액 reinvest only (no partial) — dust position 방지 + UX 단순화
  • 금액 입력 없음: [Reinvest $680] 원클릭 CTA → confirm dialog → 완료
  • min_reinvest_amount: pool config (default $50 or min_investment×50% 중 낮은 값). yield < min이면 Reinvest disabled + tooltip
  • Same-pool only (V1). Cross-pool reinvest는 V2

On-chain:pool.reinvest(totalYield) → 새 LP 토큰 민팅 (현재 NAV 기준)

Lockup: Reinvested LP는 lockup 면제 — penalty가 자연 보호막 역할 (투자자가 reinvest 후 즉시 redeem해도 early penalty 적용)

Investor UI — YOUR POSITION (allow_rollover = true):

├─ [Reinvest $680]       → primary CTA (bg-success, text-success-700)
├─ [Claim to Wallet]     → secondary (outline)
└─ [Redeem →]            → Withdraw Dialog

⚙️ allow_rollover 설정

Pool Create 시 설정 가능. ACTIVE 상태에서도 admin toggle로 on/off 가능. min_reinvest_amount도 ACTIVE에서 수정 가능 (DRAFT→ACTIVE editable).

Phase 3 — Redemption (Hybrid: Reserve + Fund Top-Up)

Unified flow for both pool types. NAV is snapshot-locked at request time. Yield is separate (claim-based, not included in redemption payout). Total redemption = token_value - penalty.

Unified Redemption Flow (Both Pool Types)

REQUESTEDPROCESSINGCOMPLETED

① Investor burns LP tokens 🔵 Investor

NAV locked at request time. redeem() called on Pool Smart Contract. LP tokens burned.

② 3-state redemption check 🟢 System

Per-investor check: lockup_end = invested_at + pool.lockup_days, maturity = invested_at + pool.maturity_days. If LOCKED (now < lockup_end) → blocked, button disabled. If EARLY (lockup_end ≤ now < maturity) → penalty applied (FLAT_FEE / PRINCIPAL_BASED / YIELD_BASED). If FREE (now ≥ maturity) → no penalty. Penalty → pool reserve.

③ Reserve check → Payout 🟢 System

Pool Contract checks reserve balance → USDC payout to investor wallet → COMPLETED.

💡 Investor sees

"Processing" → settling. "Completed" → USDC in wallet.

Failure path: Any step can transition to FAILED — tracked via failure_type + error_message. Legacy FM_ACCEPTED / REJECTED states preserved for backward compatibility only.

⚠️ Deprecated Fields

escrow_model (always SMART_CONTRACT), yield_distribution_model (always MANUAL_CLAIM), risk_tier (replaced by data-point approach). Do not expose these on forms.