Appearance
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:
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.
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 ormin_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)
REQUESTED → PROCESSING → COMPLETED
① 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.