/ token / src / network_pool.rs
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  }