Appearance
Triggers, Auto-Rules & Business Logic
Automated database triggers, business rules, and system behaviors that run without manual intervention.
Database Triggers
🔓 No Safety Bounds — NAV Auto-Adjusts
PD6 (NAV Safety Bounds) removed. No per-transaction limit, no floor. NAV auto-adjusts on default events — the market price reflects the actual asset value. Only constraint: max $1.00 cap. Investment stays open at all NAV levels — new investors pay fair current price.
⏰ Refund Timer (7-Day Auto-Refund)
On deposit creation, refund_eligible_at = now() + 7 days. If deposit status is still PENDING at that time, system auto-refunds USDC to investor. Deposit status → REFUNDED.
🔒 NAV Decrease Timelock (24 Hours)
When Oracle posts a NAV decrease, it's logged in nav_history with effective_at = now() + 24h and status PENDING. The actual pools.nav_per_token only updates after the timelock expires. NAV increases (recovery) bypass the timelock and apply immediately. Gives stakeholders time to react before a lower price takes effect.
🔗 LP Transfer Auto-Settlement
Before any LP token transfer (PLATFORM_ISSUED), unclaimed yield is auto-settled to the sender. Prevents yield loss on token movement.
Business Rules
🚫 Investment Pre-Checks
Before allowing deposit: kyc_status = APPROVED AND is_paused = false AND investment_blocked = false. NAV changes do not block investment — new investors always pay the current fair price. is_paused (manual) and investment_blocked (auto, when TVL reaches capacity) are the only two flags that block new deposits.
1️⃣ One Active Redemption Per Investment
System enforces unique constraint: only one non-terminal (not COMPLETED/REJECTED) redemption request per investment_id. Investor must wait for resolution before requesting again.
📸 NAV Snapshot on Redemption Request
nav_at_request is captured from pools.nav_per_token at request creation and never recalculated. Payout = tokens_minted × nav_at_request + accrued_yield. Protects investor from further NAV drops during processing. Also means investor doesn't benefit from NAV recovery after request.
📐 Yield on Nominal Balance
Accrued yield always calculated on nominal (original) investment amount, not NAV-adjusted token value. Formula: nominal_amount × (APY / 365) × days_held. This incentivizes investors to stay through NAV dips — they still earn full yield on their original deposit.
📋 FIFO (First-In, First-Out) Redemption Queue
Redemption requests processed oldest-first. Admin checks pool liquidity before approving. If insufficient liquidity, request stays in queue (not rejected). Admin can skip FIFO only if rejecting with reason.
- Fund Pool: FM acknowledges (FM_ACCEPTED) before sending.
- AS Pool: Depends on escrow model (auto-release, co-sign, or fund direct send).
⚖️ Early Redemption Penalty
If investor redeems during lockup period: per-pool configurable penalty applies. Types: NO_EARLY (no penalty), FLAT_FEE (fixed $), PRINCIPAL_BASED (% of principal), YIELD_BASED (% of accrued yield forfeited). Configured at pool creation.
📅 Pool Lifecycle Auto-Transitions (Scheduler)
Daily scheduler checks: (1) UPCOMING pools where start_date ≤ today → auto-transition to ACTIVE. (2) ACTIVE pools where end_date ≤ today → auto-transition to MATURED, triggering auto-redemption for all positions. DRAFT → UPCOMING requires explicit admin "Publish" action.
🚫 Investment Auto-Block (TVL Cap)
When pool TVL reaches capacity, system sets investment_blocked = true automatically. New deposits rejected until TVL drops below target (e.g., after redemptions). Admin cannot manually override — tied to TVL calculation.
🪨 SBT Mint Failure & Retry
On KYC approval (kyc_status = 'APPROVED'), system attempts SBT mint on Base L2. If tx reverts or times out: sbt_status = 'FAILED', sbt_error logged. Admin can trigger manual retry from KYC detail panel. reject_type = 'FINAL' blocks all future retry attempts.
📨 Notification Retry (3x Exponential Backoff)
Email notifications retry up to 3 times with exponential backoff before marking as FAILED. retry_count tracked in notification_logs. Failure types: BOUNCED, SPAM_FILTERED, SERVER_ERROR, TIMEOUT, INVALID_RECIPIENT, RATE_LIMITED. Failed notifications appear in Dashboard alert dropdown.
Pool Visibility Rules
🏠 Dashboard (Public)
Shows only pools where lifecycle_status IN ('UPCOMING', 'ACTIVE', 'CLOSED', 'MATURED') AND is_paused = false. DRAFT pools are never visible to investors. NAV below par does not hide a pool — investment stays open and price reflects fair value. Exception: user has an active position → pool always visible regardless of status.
📂 Portfolio (Investor)
Shows ALL user investments regardless of pool status. Paused, writedown, even offboarded pools still display with appropriate status badges.
⚙️ Admin Panel
Admin/Operator see all pools (including paused). Fund Manager only sees pools under their assigned fund(s). Oracle health status visible to Admin + Operator via /admin/oracle.