git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
9.7 KiB
9.7 KiB
Economic Edge Case Analysis for edge-net
Executive Summary
This document provides a comprehensive analysis of the edge-net economic system, identifying test coverage gaps and proposing new edge case tests across four core modules:
- credits/mod.rs - Credit ledger with CRDT and contribution curve
- evolution/mod.rs - Economic engine with distribution ratios
- tribute/mod.rs - Founding registry with vesting schedules
- rac/economics.rs - RAC staking, reputation, and rewards
Current Test Coverage Analysis
1. credits/mod.rs - Credit Ledger
Existing Tests:
- Basic contribution curve multiplier calculations
- Ledger operations (credit, deduct, stake - WASM only)
- Basic staking operations (WASM only)
Coverage Gaps Identified:
| Gap | Severity | Description |
|---|---|---|
| Credit Overflow | HIGH | No test for calculate_reward when base_reward * multiplier approaches u64::MAX |
| Negative Network Compute | MEDIUM | current_multiplier(-x) produces exp(x/constant) which explodes |
| CRDT Merge Conflicts | HIGH | No test for merge producing negative effective balance |
| Zero Division | MEDIUM | No test for zero denominators in ratio calculations |
| Staking Edge Cases | MEDIUM | No test for staking exactly balance, or stake-deduct race conditions |
2. evolution/mod.rs - Economic Engine
Existing Tests:
- Basic reward processing
- Evolution engine replication check
- Optimization node selection (basic)
Coverage Gaps Identified:
| Gap | Severity | Description |
|---|---|---|
| Treasury Depletion | HIGH | No test for treasury running out of funds |
| Distribution Ratio Sum | HIGH | No verification that ratios exactly sum to 1.0 |
| Founder Share Remainder | MEDIUM | Founder share is computed as total - others - rounding not tested |
| Sustainability Thresholds | MEDIUM | No test at exact threshold boundaries |
| Velocity Calculation | LOW | health.velocity uses magic constant 0.99 - not tested |
| Stability Edge Cases | MEDIUM | Division by zero when total_pools == 0 handled but not tested |
3. tribute/mod.rs - Founding Registry
Existing Tests:
- Basic founding registry creation
- Contribution stream processing
- Vesting schedule before/after cliff
Coverage Gaps Identified:
| Gap | Severity | Description |
|---|---|---|
| Weight Clamping | HIGH | clamp(0.01, 0.5) not tested at boundaries |
| Epoch Overflow | MEDIUM | No test for epoch values near u64::MAX |
| Multiple Founders | MEDIUM | No test for total weight > 1.0 scenario |
| Genesis Sunset | HIGH | No test for full 4-year vesting completion |
| Pool Balance Zero | MEDIUM | calculate_vested(epoch, 0) returns 0 but division not tested |
4. rac/economics.rs - RAC Economics
Existing Tests:
- Stake manager basic operations
- Reputation decay calculation
- Reward vesting and clawback
- Economic engine combined operations
- Slashing by reason
Coverage Gaps Identified:
| Gap | Severity | Description |
|---|---|---|
| Slash Saturation | HIGH | Multiple slashes exceeding stake not thoroughly tested |
| Reputation Infinity | MEDIUM | effective_score with 0 interval causes division |
| Concurrent Access | HIGH | RwLock contention under load not tested |
| Reward ID Collision | LOW | SHA256 collision probability not addressed |
| Challenge Gaming | HIGH | Winner/loser both being same node not tested |
| Zero Stake Operations | MEDIUM | Unstake/slash on zero-stake node edge cases |
Proposed Edge Case Tests
Section 1: Credit Overflow/Underflow
#[test]
fn test_credit_near_max_u64() {
// base_reward near u64::MAX with 10x multiplier
let max_safe = u64::MAX / 20;
let reward = ContributionCurve::calculate_reward(max_safe, 0.0);
assert!(reward <= u64::MAX);
}
#[test]
fn test_negative_network_compute() {
let mult = ContributionCurve::current_multiplier(-1_000_000.0);
assert!(mult.is_finite());
// exp(1) = 2.718, so mult = 1 + 9 * e = 25.4 (unsafe?)
}
Section 2: Multiplier Manipulation
#[test]
fn test_multiplier_inflation_attack() {
// Attacker rapidly inflates network_compute to reduce
// legitimate early adopter multipliers
let decay_rate = compute_decay_per_hour(100_000.0);
assert!(decay_rate < 0.15); // <15% loss per 100k hours
}
Section 3: Economic Collapse Scenarios
#[test]
fn test_sustainability_exact_threshold() {
let mut engine = EconomicEngine::new();
// Fill treasury to exactly 90 days runway
for _ in 0..optimal_reward_count {
engine.process_reward(100, 1.0);
}
assert!(engine.is_self_sustaining(100, 1000));
}
#[test]
fn test_death_spiral() {
// Low activity -> low rewards -> nodes leave -> lower activity
let mut engine = EconomicEngine::new();
// Simulate declining node count
for nodes in (10..100).rev() {
let sustainable = engine.is_self_sustaining(nodes, nodes * 10);
// Track when sustainability is lost
}
}
Section 4: Free-Rider Exploitation
#[test]
fn test_reward_without_stake() {
// Verify compute rewards require minimum stake
let stakes = StakeManager::new(100);
let node = [1u8; 32];
// Attempt to earn without staking
assert!(!stakes.has_sufficient_stake(&node));
// Economic engine should reject reward
}
#[test]
fn test_sybil_cost_barrier() {
// Verify 100 sybil nodes costs 100 * min_stake
let stakes = StakeManager::new(100);
let sybil_cost = 100 * 100;
assert_eq!(stakes.total_staked(), sybil_cost);
}
Section 5: Contribution Gaming
#[test]
fn test_founder_weight_overflow() {
let mut registry = FoundingRegistry::new();
// Register 10 founders each claiming 50% weight
for i in 0..10 {
registry.register_contributor(&format!("f{}", i), "architect", 0.5);
}
// Total weight should not exceed allocation
let total_vested = registry.calculate_vested(365 * 4, 1_000_000);
assert_eq!(total_vested, 50_000); // 5% cap enforced
}
#[test]
fn test_contribution_stream_drain() {
let mut stream = ContributionStream::new();
// Fee shares: 10% + 5% + 2% = 17%
// Remaining: 83%
let remaining = stream.process_fees(10000, 1);
assert_eq!(remaining, 8300);
}
Section 6: Treasury Depletion
#[test]
fn test_treasury_runway_calculation() {
let engine = EconomicEngine::new();
// 100 nodes * 10 rUv/day * 90 days = 90,000 rUv needed
let required = 100 * 10 * 90;
// Process rewards to fill treasury
// Treasury gets 15% of each reward
// Need: 90,000 / 0.15 = 600,000 total rewards
}
Section 7: Genesis Sunset Edge Cases
#[test]
fn test_vesting_cliff_exact_boundary() {
let registry = FoundingRegistry::new();
let cliff_epoch = (365 * 4) / 10; // 10% of 4 years
let at_cliff_minus_1 = registry.calculate_vested(cliff_epoch - 1, 1_000_000);
let at_cliff = registry.calculate_vested(cliff_epoch, 1_000_000);
assert_eq!(at_cliff_minus_1, 0);
assert!(at_cliff > 0);
}
#[test]
fn test_full_vesting_at_4_years() {
let registry = FoundingRegistry::new();
// Full 4-year vest
let full = registry.calculate_vested(365 * 4, 1_000_000);
assert_eq!(full, 50_000); // 5% of 1M
// Beyond 4 years should not exceed
let beyond = registry.calculate_vested(365 * 5, 1_000_000);
assert_eq!(beyond, 50_000);
}
Section 8: RAC Economic Attacks
#[test]
fn test_slash_cascade_attack() {
let manager = StakeManager::new(100);
let victim = [1u8; 32];
manager.stake(victim, 1000, 0);
// Cascade: Equivocation + Sybil = 50% + 100% of remainder
manager.slash(&victim, SlashReason::Equivocation, vec![]);
manager.slash(&victim, SlashReason::SybilAttack, vec![]);
assert_eq!(manager.get_stake(&victim), 0);
}
#[test]
fn test_reputation_negative_protection() {
let manager = ReputationManager::new(0.1, 86400_000);
let node = [1u8; 32];
manager.register(node);
// Massive failure count
for _ in 0..1000 {
manager.record_failure(&node, 1.0);
}
let rep = manager.get_reputation(&node);
assert!(rep >= 0.0, "Reputation should never go negative");
}
Priority Matrix
| Priority | Tests | Rationale |
|---|---|---|
| P0 (Critical) | Credit overflow, Distribution ratio sum, Slash saturation, CRDT merge conflicts | Could cause token inflation or fund loss |
| P1 (High) | Treasury depletion, Sybil cost, Vesting cliff, Free-rider protection | Economic sustainability attacks |
| P2 (Medium) | Multiplier manipulation, Founder weight clamping, Reputation bounds | Gaming prevention |
| P3 (Low) | Velocity calculation, Mutation rate decay, Unknown node scoring | Minor edge cases |
Implementation Status
Tests have been implemented in:
/workspaces/ruvector/examples/edge-net/tests/economic_edge_cases_test.rs
To run the tests:
cd /workspaces/ruvector/examples/edge-net
cargo test --test economic_edge_cases_test
Recommendations
-
Immediate Actions:
- Add overflow protection with
checked_mulincalculate_reward - Validate network_compute is non-negative before multiplier calculation
- Add explicit tests for CRDT merge conflict resolution
- Add overflow protection with
-
Short-term:
- Implement minimum stake enforcement in compute reward path
- Add comprehensive vesting schedule tests at all boundaries
- Create stress tests for concurrent stake/slash operations
-
Long-term:
- Consider formal verification for critical economic invariants
- Add fuzzing tests for numeric edge cases
- Implement economic simulation tests for collapse scenarios