network_pool.rs
1 // Copyright (c) 2025 ADnet Contributors 2 // SPDX-License-Identifier: Apache-2.0 3 4 //! Network Pool Management (F-N01) 5 //! 6 //! The Network Pool provides DX tokens to bootstrap the DELTA network: 7 //! - Validator staking (Governors and Public validators) 8 //! - Early prover performance gifts 9 //! 10 //! # Genesis Allocations (Testing Values) 11 //! 12 //! | Participant | Stake/Gift | Count | Total DX | 13 //! |-------------|------------|-------|----------| 14 //! | Governors | 1,000,000 DX | 150 | 150M | 15 //! | Public Validators | 100,000 DX | 150 | 15M | 16 //! | Early Provers | 10,000 DX gift | 3,000 | 30M | 17 //! | **Total Expected** | | | **195M** | 18 //! | **Pool Allocation** | | | **250M** | 19 //! | **Buffer** | | | **55M** | 20 //! 21 //! # Closure Rules 22 //! 23 //! When ALPHA chain reaches maturity (150+ Governors), governance MAY vote 24 //! to close the Network Pool. Closure can ONLY transfer remaining DX to 25 //! the Reward Pool - no other destination is allowed. 26 27 use anyhow::{ensure, Result}; 28 use serde::{Deserialize, Serialize}; 29 30 // ============================================================================ 31 // Genesis Constants (Testing Values) 32 // ============================================================================ 33 34 /// Total DX supply (1 billion, 0 decimals) 35 pub const TOTAL_DX_SUPPLY: u64 = 1_000_000_000; 36 37 /// Founder allocation 38 pub const GENESIS_FOUNDER_ALLOCATION: u64 = 300_000_000; 39 40 /// Investor allocation 41 pub const GENESIS_INVESTOR_ALLOCATION: u64 = 100_000_000; 42 43 /// Network Pool allocation 44 pub const GENESIS_NETWORK_POOL: u64 = 250_000_000; 45 46 /// Initial Reward Pool allocation (remainder) 47 pub const GENESIS_REWARD_POOL: u64 = TOTAL_DX_SUPPLY 48 - GENESIS_FOUNDER_ALLOCATION 49 - GENESIS_INVESTOR_ALLOCATION 50 - GENESIS_NETWORK_POOL; // = 350,000,000 51 52 /// Governor validator stake requirement 53 pub const GOVERNOR_STAKE: u64 = 1_000_000; 54 55 /// Public validator stake requirement 56 pub const PUBLIC_VALIDATOR_STAKE: u64 = 100_000; 57 58 /// Early prover performance gift 59 pub const PROVER_GIFT: u64 = 10_000; 60 61 /// Expected number of governors 62 pub const EXPECTED_GOVERNORS: u64 = 150; 63 64 /// Expected number of public validators 65 pub const EXPECTED_PUBLIC_VALIDATORS: u64 = 150; 66 67 /// Expected number of early provers 68 pub const EXPECTED_PROVERS: u64 = 3_000; 69 70 /// Minimum governors on ALPHA for Network Pool closure eligibility 71 pub const MIN_GOVERNORS_FOR_CLOSURE: u64 = 150; 72 73 // ============================================================================ 74 // Network Pool State 75 // ============================================================================ 76 77 /// Network Pool for bootstrapping the DELTA network 78 #[derive(Clone, Debug, Serialize, Deserialize)] 79 pub struct NetworkPool { 80 /// Remaining DX in the pool 81 balance: u64, 82 /// Total DX allocated to governors 83 allocated_governors: u64, 84 /// Total DX allocated to public validators 85 allocated_public_validators: u64, 86 /// Total DX gifted to provers 87 gifted_provers: u64, 88 /// Number of governors funded 89 governor_count: u64, 90 /// Number of public validators funded 91 public_validator_count: u64, 92 /// Number of provers gifted 93 prover_count: u64, 94 /// Whether the pool is closed 95 is_closed: bool, 96 /// Epoch when closed (if closed) 97 closed_epoch: Option<u64>, 98 /// Amount transferred to Reward Pool on closure 99 transferred_to_reward_pool: u64, 100 } 101 102 impl Default for NetworkPool { 103 fn default() -> Self { 104 Self::genesis() 105 } 106 } 107 108 impl NetworkPool { 109 /// Create Network Pool at genesis 110 pub fn genesis() -> Self { 111 Self { 112 balance: GENESIS_NETWORK_POOL, 113 allocated_governors: 0, 114 allocated_public_validators: 0, 115 gifted_provers: 0, 116 governor_count: 0, 117 public_validator_count: 0, 118 prover_count: 0, 119 is_closed: false, 120 closed_epoch: None, 121 transferred_to_reward_pool: 0, 122 } 123 } 124 125 /// Create with custom initial balance (for testing) 126 pub fn with_balance(balance: u64) -> Self { 127 Self { 128 balance, 129 ..Self::default() 130 } 131 } 132 133 // ======================================================================== 134 // Validator Operations 135 // ======================================================================== 136 137 /// Allocate stake to a Governor validator 138 /// 139 /// Governor validators receive 1,000,000 DX stake from the Network Pool. 140 pub fn allocate_governor(&mut self) -> Result<u64> { 141 ensure!(!self.is_closed, "Network Pool is closed"); 142 ensure!( 143 self.balance >= GOVERNOR_STAKE, 144 "Insufficient Network Pool balance for governor stake" 145 ); 146 147 self.balance -= GOVERNOR_STAKE; 148 self.allocated_governors += GOVERNOR_STAKE; 149 self.governor_count += 1; 150 151 Ok(GOVERNOR_STAKE) 152 } 153 154 /// Allocate stake to a Public validator 155 /// 156 /// Public validators receive 100,000 DX stake from the Network Pool. 157 pub fn allocate_public_validator(&mut self) -> Result<u64> { 158 ensure!(!self.is_closed, "Network Pool is closed"); 159 ensure!( 160 self.balance >= PUBLIC_VALIDATOR_STAKE, 161 "Insufficient Network Pool balance for validator stake" 162 ); 163 164 self.balance -= PUBLIC_VALIDATOR_STAKE; 165 self.allocated_public_validators += PUBLIC_VALIDATOR_STAKE; 166 self.public_validator_count += 1; 167 168 Ok(PUBLIC_VALIDATOR_STAKE) 169 } 170 171 /// Gift DX to an early prover 172 /// 173 /// Early provers receive 10,000 DX as a performance gift. 174 pub fn gift_prover(&mut self) -> Result<u64> { 175 ensure!(!self.is_closed, "Network Pool is closed"); 176 ensure!( 177 self.balance >= PROVER_GIFT, 178 "Insufficient Network Pool balance for prover gift" 179 ); 180 ensure!( 181 self.prover_count < EXPECTED_PROVERS, 182 "Maximum prover gifts already distributed" 183 ); 184 185 self.balance -= PROVER_GIFT; 186 self.gifted_provers += PROVER_GIFT; 187 self.prover_count += 1; 188 189 Ok(PROVER_GIFT) 190 } 191 192 // ======================================================================== 193 // Closure Operations 194 // ======================================================================== 195 196 /// Check if closure is allowed 197 /// 198 /// Closure requires ALPHA chain to have reached maturity (150+ Governors). 199 pub fn can_close(&self, alpha_governor_count: u64) -> bool { 200 !self.is_closed && alpha_governor_count >= MIN_GOVERNORS_FOR_CLOSURE 201 } 202 203 /// Close the Network Pool (governance action) 204 /// 205 /// # Rules 206 /// - Requires ALPHA chain maturity (150+ Governors) 207 /// - ALL remaining DX transfers to Reward Pool (no other destination) 208 /// - Pool becomes permanently closed 209 /// 210 /// # Returns 211 /// Amount of DX transferred to Reward Pool 212 pub fn close(&mut self, alpha_governor_count: u64, current_epoch: u64) -> Result<u64> { 213 ensure!(!self.is_closed, "Network Pool is already closed"); 214 ensure!( 215 alpha_governor_count >= MIN_GOVERNORS_FOR_CLOSURE, 216 "ALPHA chain not mature enough (need {} governors, have {})", 217 MIN_GOVERNORS_FOR_CLOSURE, 218 alpha_governor_count 219 ); 220 221 let transfer_amount = self.balance; 222 223 self.transferred_to_reward_pool = transfer_amount; 224 self.balance = 0; 225 self.is_closed = true; 226 self.closed_epoch = Some(current_epoch); 227 228 Ok(transfer_amount) 229 } 230 231 // ======================================================================== 232 // Getters 233 // ======================================================================== 234 235 /// Get current balance 236 pub fn balance(&self) -> u64 { 237 self.balance 238 } 239 240 /// Check if pool is closed 241 pub fn is_closed(&self) -> bool { 242 self.is_closed 243 } 244 245 /// Get closure epoch 246 pub fn closed_epoch(&self) -> Option<u64> { 247 self.closed_epoch 248 } 249 250 /// Get amount transferred to Reward Pool on closure 251 pub fn transferred_to_reward_pool(&self) -> u64 { 252 self.transferred_to_reward_pool 253 } 254 255 /// Get total allocated to governors 256 pub fn allocated_governors(&self) -> u64 { 257 self.allocated_governors 258 } 259 260 /// Get total allocated to public validators 261 pub fn allocated_public_validators(&self) -> u64 { 262 self.allocated_public_validators 263 } 264 265 /// Get total gifted to provers 266 pub fn gifted_provers(&self) -> u64 { 267 self.gifted_provers 268 } 269 270 /// Get governor count 271 pub fn governor_count(&self) -> u64 { 272 self.governor_count 273 } 274 275 /// Get public validator count 276 pub fn public_validator_count(&self) -> u64 { 277 self.public_validator_count 278 } 279 280 /// Get prover count 281 pub fn prover_count(&self) -> u64 { 282 self.prover_count 283 } 284 285 /// Get total distributed from pool 286 pub fn total_distributed(&self) -> u64 { 287 self.allocated_governors + self.allocated_public_validators + self.gifted_provers 288 } 289 290 /// Get statistics 291 pub fn statistics(&self) -> NetworkPoolStatistics { 292 NetworkPoolStatistics { 293 balance: self.balance, 294 allocated_governors: self.allocated_governors, 295 allocated_public_validators: self.allocated_public_validators, 296 gifted_provers: self.gifted_provers, 297 governor_count: self.governor_count, 298 public_validator_count: self.public_validator_count, 299 prover_count: self.prover_count, 300 total_distributed: self.total_distributed(), 301 is_closed: self.is_closed, 302 closed_epoch: self.closed_epoch, 303 transferred_to_reward_pool: self.transferred_to_reward_pool, 304 } 305 } 306 } 307 308 // ============================================================================ 309 // Statistics 310 // ============================================================================ 311 312 /// Public statistics about the Network Pool 313 #[derive(Clone, Debug, Serialize, Deserialize)] 314 pub struct NetworkPoolStatistics { 315 /// Current balance 316 pub balance: u64, 317 /// Total allocated to governors 318 pub allocated_governors: u64, 319 /// Total allocated to public validators 320 pub allocated_public_validators: u64, 321 /// Total gifted to provers 322 pub gifted_provers: u64, 323 /// Number of governors funded 324 pub governor_count: u64, 325 /// Number of public validators funded 326 pub public_validator_count: u64, 327 /// Number of provers gifted 328 pub prover_count: u64, 329 /// Total distributed 330 pub total_distributed: u64, 331 /// Whether closed 332 pub is_closed: bool, 333 /// Closure epoch 334 pub closed_epoch: Option<u64>, 335 /// Amount transferred to Reward Pool 336 pub transferred_to_reward_pool: u64, 337 } 338 339 // ============================================================================ 340 // Tests 341 // ============================================================================ 342 343 #[cfg(test)] 344 mod tests { 345 use super::*; 346 347 #[test] 348 fn test_genesis_constants() { 349 // Verify allocations sum to total supply 350 let total = GENESIS_FOUNDER_ALLOCATION 351 + GENESIS_INVESTOR_ALLOCATION 352 + GENESIS_NETWORK_POOL 353 + GENESIS_REWARD_POOL; 354 assert_eq!(total, TOTAL_DX_SUPPLY); 355 356 // Verify individual values 357 assert_eq!(GENESIS_FOUNDER_ALLOCATION, 300_000_000); 358 assert_eq!(GENESIS_INVESTOR_ALLOCATION, 100_000_000); 359 assert_eq!(GENESIS_NETWORK_POOL, 250_000_000); 360 assert_eq!(GENESIS_REWARD_POOL, 350_000_000); 361 } 362 363 #[test] 364 fn test_expected_network_usage() { 365 // Verify expected usage fits in Network Pool 366 let expected_usage = (GOVERNOR_STAKE * EXPECTED_GOVERNORS) 367 + (PUBLIC_VALIDATOR_STAKE * EXPECTED_PUBLIC_VALIDATORS) 368 + (PROVER_GIFT * EXPECTED_PROVERS); 369 370 assert_eq!(expected_usage, 195_000_000); 371 assert!(expected_usage < GENESIS_NETWORK_POOL); 372 373 // Buffer 374 let buffer = GENESIS_NETWORK_POOL - expected_usage; 375 assert_eq!(buffer, 55_000_000); 376 } 377 378 #[test] 379 fn test_genesis_pool() { 380 let pool = NetworkPool::genesis(); 381 assert_eq!(pool.balance(), GENESIS_NETWORK_POOL); 382 assert!(!pool.is_closed()); 383 } 384 385 #[test] 386 fn test_allocate_governor() { 387 let mut pool = NetworkPool::genesis(); 388 389 let amount = pool.allocate_governor().unwrap(); 390 assert_eq!(amount, GOVERNOR_STAKE); 391 assert_eq!(pool.governor_count(), 1); 392 assert_eq!(pool.allocated_governors(), GOVERNOR_STAKE); 393 assert_eq!(pool.balance(), GENESIS_NETWORK_POOL - GOVERNOR_STAKE); 394 } 395 396 #[test] 397 fn test_allocate_public_validator() { 398 let mut pool = NetworkPool::genesis(); 399 400 let amount = pool.allocate_public_validator().unwrap(); 401 assert_eq!(amount, PUBLIC_VALIDATOR_STAKE); 402 assert_eq!(pool.public_validator_count(), 1); 403 } 404 405 #[test] 406 fn test_gift_prover() { 407 let mut pool = NetworkPool::genesis(); 408 409 let amount = pool.gift_prover().unwrap(); 410 assert_eq!(amount, PROVER_GIFT); 411 assert_eq!(pool.prover_count(), 1); 412 assert_eq!(pool.gifted_provers(), PROVER_GIFT); 413 } 414 415 #[test] 416 fn test_prover_limit() { 417 let mut pool = NetworkPool::with_balance(50_000_000); // Enough for all provers 418 419 // Gift to max provers 420 for _ in 0..EXPECTED_PROVERS { 421 pool.gift_prover().unwrap(); 422 } 423 424 // Next should fail 425 assert!(pool.gift_prover().is_err()); 426 } 427 428 #[test] 429 fn test_closure_requires_maturity() { 430 let mut pool = NetworkPool::genesis(); 431 432 // Cannot close with fewer than 150 governors 433 assert!(!pool.can_close(100)); 434 assert!(pool.close(100, 0).is_err()); 435 436 // Can close with 150+ governors 437 assert!(pool.can_close(150)); 438 } 439 440 #[test] 441 fn test_closure_transfers_to_reward_pool() { 442 let mut pool = NetworkPool::genesis(); 443 444 // Allocate some 445 pool.allocate_governor().unwrap(); 446 pool.allocate_public_validator().unwrap(); 447 448 let remaining = pool.balance(); 449 450 // Close 451 let transferred = pool.close(150, 100).unwrap(); 452 453 assert_eq!(transferred, remaining); 454 assert_eq!(pool.balance(), 0); 455 assert!(pool.is_closed()); 456 assert_eq!(pool.closed_epoch(), Some(100)); 457 assert_eq!(pool.transferred_to_reward_pool(), remaining); 458 } 459 460 #[test] 461 fn test_cannot_allocate_after_closure() { 462 let mut pool = NetworkPool::genesis(); 463 pool.close(150, 0).unwrap(); 464 465 // All operations should fail 466 assert!(pool.allocate_governor().is_err()); 467 assert!(pool.allocate_public_validator().is_err()); 468 assert!(pool.gift_prover().is_err()); 469 } 470 471 #[test] 472 fn test_cannot_close_twice() { 473 let mut pool = NetworkPool::genesis(); 474 pool.close(150, 0).unwrap(); 475 476 assert!(pool.close(150, 1).is_err()); 477 } 478 479 #[test] 480 fn test_statistics() { 481 let mut pool = NetworkPool::genesis(); 482 pool.allocate_governor().unwrap(); 483 pool.gift_prover().unwrap(); 484 485 let stats = pool.statistics(); 486 487 assert_eq!(stats.governor_count, 1); 488 assert_eq!(stats.prover_count, 1); 489 assert_eq!(stats.total_distributed, GOVERNOR_STAKE + PROVER_GIFT); 490 assert!(!stats.is_closed); 491 } 492 }