Skip to content

feat: Implement investor participant counter and maximum investor cap (#105)#149

Open
Nanle-code wants to merge 4 commits into
StellarYield:mainfrom
Nanle-code:Investor
Open

feat: Implement investor participant counter and maximum investor cap (#105)#149
Nanle-code wants to merge 4 commits into
StellarYield:mainfrom
Nanle-code:Investor

Conversation

@Nanle-code
Copy link
Copy Markdown

This PR implements the investor participant counter and maximum investor cap feature to support regulatory compliance for private securities offerings.

🎯 Problem Solved

Many regulatory frameworks (e.g., Regulation D in the US, MiFID II in Europe) limit the number of investors in private securities offerings. The vault previously had no concept of investor count — anyone who passed KYC could deposit regardless of how many other investors already held shares.

Features Implemented

Core Functionality

  • Investor Count Tracking: Automatically tracks unique share holders in instance storage
  • Maximum Investor Cap: Configurable limit on total unique investors (0 = unlimited)
  • Smart Enforcement: Cap enforced only for new investors, existing investors unaffected
  • Automatic Cleanup: Investor count decrements when users fully exit (balance becomes 0)

Public API

  • investor_count() -> u32 - Returns current unique investor count
  • max_investors() -> u32 - Returns configured maximum investor cap
  • set_max_investors(caller, max) -> () - Admin-only cap adjustment

Error Handling

  • MaxInvestorsReached error when cap exceeded by new investors
  • Graceful handling of edge cases and transfer scenarios

🔧 Technical Implementation

Storage Layer

  • DataKey::InvestorCount → u32 (instance storage)
  • DataKey::MaxInvestors → u32 (instance storage)
  • Getter/setter functions with proper TTL management

Business Logic

  • Deposit/Mint: Check if user is new investor (balance == 0), enforce cap, increment count
  • Withdraw/Redeem: Decrement count when user balance becomes 0
  • Transfers: Handled correctly - count follows share ownership

Configuration

  • max_investors: u32 field added to InitParams
  • Default value of 100 in test helpers
  • Runtime updates via admin function

🧪 Comprehensive Testing

Created extensive test suite (test_investor_count.rs) covering:

  • ✅ Investor count increments on first deposit/mint
  • ✅ No increment on additional deposits from same user
  • ✅ Count decrements on full withdraw/redeem
  • ✅ No decrement on partial withdrawals
  • ✅ Max investor cap enforcement
  • ✅ Unlimited investors when cap = 0
  • ✅ Re-entry after exit scenarios
  • ✅ Admin-only functions
  • ✅ Transfer impact on investor count

📋 Requirements Fulfilled

  • Add DataKey::InvestorCount → u32 in instance storage
  • Add max_investors: u32 field to InitParams (0 = unlimited)
  • Track unique investors with increment/decrement logic
  • Enforce cap with Error::MaxInvestorsReached panic
  • Add view functions: investor_count(), max_investors()
  • Add admin-only set_max_investors(caller, max) function
  • Handle transfer edge cases correctly
  • Comprehensive test coverage

🏛️ Regulatory Compliance

This implementation enables compliance with:

  • Regulation D (US): Limit to 35 non-accredited investors
  • MiFID II (Europe): Similar investor thresholds
  • Custom Requirements: Any limit configurable via max_investors

🔒 Security Considerations

  • Gas Efficient: Minimal storage reads/writes
  • Reentrancy Safe: Follows existing CEI pattern
  • Access Control: Admin-only functions properly protected
  • Edge Case Handling: Prevents negative investor counts

📁 Files Modified

  • src/lib.rs - Core business logic
  • src/storage.rs - New storage keys and functions
  • src/types.rs - InitParams extension
  • src/errors.rs - New error variant
  • src/test_investor_count.rs - New test suite
  • src/test_helpers.rs - Updated for new fields

🚀 Breaking Changes

  • InitParams: New max_investors and lock_up_period fields (backward compatible)
  • Existing Tests: Updated to include new fields

📊 Definition of Done - Complete

  • Investor count tracks unique share holders
  • Max investor cap enforced on new deposits
  • Count decrements when users fully exit
  • Admin can update the cap
  • Tests cover: cap enforcement, re-entry after exit, transfer impact

Closes #105

…ks (StellarYield#104)

- Add Error::InsufficientVaultBalance variant for clearer diagnostics
- Add explicit balance checks before all outgoing transfers in transfer_asset_from_vault
- Wrap transfer_asset_to_vault to catch insufficient user balance scenarios
- Add vault_asset_balance() public view function for frontend solvency verification
- Document atomicity assumptions in all functions combining state changes with external calls
- Add comprehensive tests for insufficient balance scenarios

Addresses vault state inconsistency when token transfers fail by providing
explicit balance checks and clear error diagnostics instead of opaque
token contract failures.
Add comprehensive investor tracking and cap enforcement for regulatory
compliance in private securities offerings.

Features:
- Track unique investors with automatic increment/decrement
- Configurable maximum investor cap (0 = unlimited)
- Admin-only cap adjustment function
- MaxInvestorsReached error for cap enforcement
- Comprehensive view functions and test coverage

Supports compliance with Regulation D (35 non-accredited investors)
and MiFID II frameworks. Handles transfer edge cases and maintains
gas efficiency.

Closes StellarYield#105
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Mar 26, 2026

@Nanle-code Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Investor Participant Counter and Maximum Investor Cap

1 participant