Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 215 additions & 22 deletions contracts/predictify-hybrid/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,270 @@ use crate::errors::Error;
/// - Configuration documentation and testing utilities
/// - Modular configuration system for easier maintenance

// ===== CORE CONSTANTS =====
// ===== CORE MARKET CONSTANTS =====
//
// RATIONALE: Market structure limits ensure:
// 1. Contract performance - bounded iteration over outcomes
// 2. User experience - meaningful markets without clutter
// 3. Storage efficiency - predictable state size
//
// SAFE RANGES: Derived from:
// - Soroban storage cost analysis
// - UI/UX best practices for prediction markets
// - Competitive analysis (Polymarket, Augur limits)
// - Security review of DoS vectors
//
// THREAT MODEL: Market creation is open but fee-gated. Admins cannot
// bypass duration/outcome limits. Excessive creation is limited by
// creation fees and per-creator active event caps.
//
// INVARIANTS PROVEN:
// - Market duration is always within [MIN_MARKET_DURATION_DAYS, MAX_MARKET_DURATION_DAYS]
// - Outcome count is always within [MIN_MARKET_OUTCOMES, MAX_MARKET_OUTCOMES]
// - Question/outcome lengths are bounded by documented maxima
//
// EXPLICIT NON-GOALS:
// - These limits do not prevent market manipulation
// - Duration limits do not guarantee oracle availability

/// Percentage denominator for calculations (100%)
///
/// Rationale: Used as denominator for fee percentage calculations.
/// Represented as basis points * 100 for precision (e.g., 250 = 2.5%).
pub const PERCENTAGE_DENOMINATOR: i128 = 100;

/// Maximum market duration in days
/// Maximum market duration in days (365)
///
/// Rationale: 1-year maximum prevents oracle reliability issues for
/// long-range predictions. Studies show prediction accuracy degrades
/// significantly beyond 6 months for most markets.
///
/// Safe range: 30-730 days. Below 30 days limits short-term markets.
/// Above 730 days (2 years) risks oracle provider changes and
/// blockchain state bloat.
///
/// Security note: Longer durations increase oracle manipulation window.
pub const MAX_MARKET_DURATION_DAYS: u32 = 365;

/// Minimum market duration in days
/// Minimum market duration in days (1)
///
/// Rationale: 1-day minimum ensures meaningful market activity before
/// resolution. Prevents "flash crash" markets that resolve in minutes.
///
/// Safe range: 1-7 days. Below 1 day risks insufficient participation.
/// Above 7 days may block time-sensitive events.
pub const MIN_MARKET_DURATION_DAYS: u32 = 1;

/// Maximum number of outcomes per market
/// Maximum number of outcomes per market (10)
///
/// Rationale: 10 outcomes balance flexibility with contract performance.
/// Each outcome requires storage and iteration during resolution.
/// Complex multi-outcome markets can use categorical bucketing.
///
/// Safe range: 2-100. Below 2 eliminates binary markets. Above 100
/// creates storage/UX issues and potential iteration gas bombs.
pub const MAX_MARKET_OUTCOMES: u32 = 10;

/// Minimum number of outcomes per market
/// Minimum number of outcomes per market (2)
///
/// Rationale: Binary markets (Yes/No) are the prediction market
/// foundation. Single-outcome markets have no trading value.
///
/// Safe range: Exactly 2 minimum. Fewer outcomes = no prediction.
pub const MIN_MARKET_OUTCOMES: u32 = 2;

/// Maximum question length in characters
/// Maximum question length in characters (500)
///
/// Rationale: 500 chars allows detailed questions while preventing
/// gas-bomb questions that could strain RPC nodes and UI rendering.
///
/// Safe range: 100-2000 chars. Below 100 may be too restrictive for
/// nuanced questions. Above 2000 risks storage and display issues.
pub const MAX_QUESTION_LENGTH: u32 = 500;

/// Minimum question length in characters
/// Minimum question length in characters (10)
///
/// Rationale: 10 chars minimum prevents spam questions like "?" or "yes".
/// Forces meaningful question formulation.
///
/// Safe range: 5-50 chars. Below 5 is trivial spam. Above 50 may block
/// legitimate concise questions.
pub const MIN_QUESTION_LENGTH: u32 = 10;

/// Maximum outcome length in characters
/// Maximum outcome length in characters (100)
///
/// Rationale: 100 chars sufficient for outcome descriptions (e.g.,
/// "Bitcoin above $100,000 by Dec 31 2024"). Prevents gas bombs.
///
/// Safe range: 20-500 chars. Below 20 too restrictive. Above 500
/// creates storage/UX issues.
pub const MAX_OUTCOME_LENGTH: u32 = 100;

/// Minimum outcome length in characters
/// Minimum outcome length in characters (2)
///
/// Rationale: 2 chars minimum (e.g., "Yes", "No") prevents empty outcomes.
///
/// Safe range: 1-10 chars. Below 1 is invalid. Above 10 may be too strict.
pub const MIN_OUTCOME_LENGTH: u32 = 2;

/// Maximum description length in characters
/// Maximum description length in characters (1000)
///
/// Rationale: 1000 chars allows detailed market descriptions, rules,
/// and edge case specifications without gas abuse.
///
/// Safe range: 100-5000 chars. Balances detail with storage costs.
pub const MAX_DESCRIPTION_LENGTH: u32 = 1000;

/// Minimum description length in characters (optional field, can be 0)
/// Minimum description length in characters (0 = optional)
///
/// Rationale: 0 means descriptions are optional. Prevents forcing
/// empty descriptions on simple markets.
///
/// Safe range: 0-100 chars. 0 = no minimum (field is optional).
pub const MIN_DESCRIPTION_LENGTH: u32 = 0;

/// Maximum tag length in characters
/// Maximum tag length in characters (50)
///
/// Rationale: 50 chars sufficient for category tags (e.g., "crypto",
/// "politics", "sports") while preventing injection attacks.
///
/// Safe range: 10-200 chars. Prevents oversized tag storage.
pub const MAX_TAG_LENGTH: u32 = 50;

/// Minimum tag length in characters
/// Minimum tag length in characters (2)
///
/// Rationale: 2 chars minimum prevents single-character spam tags.
///
/// Safe range: 1-5 chars. Below 1 is invalid.
pub const MIN_TAG_LENGTH: u32 = 2;

/// Maximum number of tags per market
/// Maximum number of tags per market (10)
///
/// Rationale: 10 tags provides adequate categorization without
/// enabling tag spam or storage abuse.
///
/// Safe range: 3-20. Balances discoverability with storage.
pub const MAX_TAGS_PER_MARKET: u32 = 10;

/// Maximum category name length in characters
/// Maximum category name length in characters (100)
///
/// Rationale: 100 chars sufficient for category hierarchies and
/// internationalization (e.g., "US Politics/Elections/2024").
///
/// Safe range: 20-500 chars.
pub const MAX_CATEGORY_LENGTH: u32 = 100;

/// Minimum category name length in characters
/// Minimum category name length in characters (2)
///
/// Rationale: 2 chars minimum (e.g., "AI", "Web3") prevents empty categories.
///
/// Safe range: 1-10 chars.
pub const MIN_CATEGORY_LENGTH: u32 = 2;

// ===== FEE CONSTANTS =====
//
// RATIONALE: Fees serve multiple purposes:
// 1. Platform sustainability - cover operational costs (oracle feeds, infrastructure)
// 2. Spam prevention - creation costs deter low-quality market submissions
// 3. Economic alignment - skin in the game ensures serious participants
//
// SAFE RANGES: These bounds are derived from:
// - Competitive analysis with other prediction markets (0.5-10% platform fees)
// - Stellar network transaction cost analysis (dust prevention)
// - Economic modeling for platform sustainability
// - Security review to prevent fee manipulation attacks
//
// THREAT MODEL: Fee configuration is admin-protected. Unauthorized fee changes
// could drain user funds or enable griefing. The max fee cap prevents runaway
// fees even if admin is compromised.
//
// INVARIANTS PROVEN:
// - creation_fee is always within [min_fee_amount, max_fee_amount]
// - platform_fee_percentage is always within [MIN_PLATFORM_FEE_PERCENTAGE, MAX_PLATFORM_FEE_PERCENTAGE]
// - min_fee_amount < max_fee_amount (enforced by validation)
//
// EXPLICIT NON-GOALS:
// - Fee changes do not affect already-created markets
// - Fee configuration does not handle token price volatility

/// Default platform fee percentage (2%)
///
/// Rationale: 2% strikes balance between sustainability (competitive with
/// Polymarket's ~1-2%) and user accessibility. Low enough to encourage
/// participation, high enough to sustain operations.
///
/// Safe range: 0-10%. Below 1% may not cover operational costs at low volume.
/// Above 5% may deter serious market creators. 10% is a hard cap to prevent
/// admin abuse even under compromise scenarios.
///
/// Environment notes:
/// - Development: 2% (relaxed for testing)
/// - Testnet: 2% (mirrors production)
/// - Mainnet: 3% (higher for sustainability with real value)
pub const DEFAULT_PLATFORM_FEE_PERCENTAGE: i128 = 2;

/// Default market creation fee (1 XLM)
/// Default market creation fee (1 XLM = 10_000_000 stroops)
///
/// Rationale: 1 XLM creation fee prevents spam while remaining accessible.
/// At ~$0.10/XLM (testnet), this is negligible. On mainnet, this covers
/// basic oracle setup and storage costs without being prohibitive.
///
/// Safe range: 0.1-10 XLM. Lower bounds (0.1 XLM) still deter simple spam
/// attacks. Upper bounds (10 XLM) allow serious markets without blocking
/// smaller participants.
///
/// Calculation basis: ~0.01 XLM per 1KB storage + oracle provider setup fee
pub const DEFAULT_MARKET_CREATION_FEE: i128 = 10_000_000;

/// Minimum fee amount (0.1 XLM)
/// Minimum fee amount (0.1 XLM = 1_000_000 stroops)
///
/// Rationale: 0.1 XLM floor prevents dust transactions that could clog
/// Stellar network and waste validators' resources. This is ~10x typical
/// Stellar transaction fee, ensuring only meaningful operations proceed.
///
/// Safe range: 0.01-1 XLM. Below 0.01 XLM provides negligible spam
/// protection. Above 1 XLM may block micro-markets.
pub const MIN_FEE_AMOUNT: i128 = 1_000_000;

/// Maximum fee amount (100 XLM)
/// Maximum fee amount (100 XLM = 1_000_000_000 stroops)
///
/// Rationale: Hard cap prevents runaway fees even if admin is compromised
/// or oracle prices spike. 100 XLM is ~$10 at current XLM prices,
/// reasonable for high-stakes prediction markets.
///
/// Safe range: 10-10000 XLM. Below 10 XLM may be too restrictive for
/// serious markets. Above 10000 XLM creates excessive risk.
pub const MAX_FEE_AMOUNT: i128 = 1_000_000_000;

/// Fee collection threshold (10 XLM)
/// Fee collection threshold (10 XLM = 100_000_000 stroops)
///
/// Rationale: Automatic collection at 10 XLM balances gas efficiency
/// (fewer individual collections) with liquidity management (fees not
/// sitting idle too long). Collection is triggered by reaching threshold
/// to reduce storage accumulation.
///
/// Safe range: 1-100 XLM. Lower values increase collection frequency
/// and gas costs. Higher values tie up more platform funds.
pub const FEE_COLLECTION_THRESHOLD: i128 = 100_000_000;

/// Maximum platform fee percentage
/// Maximum platform fee percentage (10%)
///
/// Rationale: 10% hard cap is a security measure. Even if admin is
/// compromised, this prevents catastrophic fee extraction. This is
/// ~5x typical market rates but within competitive range.
///
/// Security note: This is NOT the same as market-specific fee caps.
/// It's a global upper bound enforced at the contract level.
pub const MAX_PLATFORM_FEE_PERCENTAGE: i128 = 10;

/// Minimum platform fee percentage
/// Minimum platform fee percentage (0%)
///
/// Rationale: 0% allows promotional periods with zero platform fees
/// to bootstrap markets. Admin can disable fees entirely for testing
/// or competitive reasons.
///
/// Security note: When fees are 0%, creation fees may still apply
/// depending on market configuration.
pub const MIN_PLATFORM_FEE_PERCENTAGE: i128 = 0;

// ===== VOTING CONSTANTS =====
Expand Down
Loading