oil_api/state/
auction.rs

1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::auction_pda;
5use crate::consts::ONE_OIL;
6
7use super::OilAccount;
8
9/// Singleton auction configuration account
10#[repr(C)]
11#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
12pub struct Auction {
13    /// [REPURPOSED] Total OIL minted from auction-based mining (in atomic units)
14    /// Used for supply-based halving: halvings occur at 1M, 2.5M, 5M, 10M, etc. OIL
15    /// Originally: halving_period_seconds (no longer used for time-based halving)
16    pub halving_period_seconds: u64,
17    
18    /// [REPURPOSED] Number of halvings that have been applied (starts at 0)
19    /// Each halving reduces rates by 25% (multiply by 0.75)
20    /// Originally: last_halving_time (no longer used for time-based halving)
21    pub last_halving_time: u64,
22    
23    /// Base mining rates per well (OIL per second, in atomic units)
24    /// Macaron's rates: totaling 4.0 OIL/s
25    /// - Well 0 (Seep): 0.4 OIL/s = 40,000,000,000 atomic units/s
26    /// - Well 1 (Flow): 0.8 OIL/s = 80,000,000,000 atomic units/s
27    /// - Well 2 (Gusher): 1.2 OIL/s = 120,000,000,000 atomic units/s
28    /// - Well 3 (Blowout): 1.6 OIL/s = 160,000,000,000 atomic units/s
29    /// Total: 4.0 OIL/s (matches Macaron's rates)
30    /// Creates meaningful trade-offs: higher rates = higher competition & prices
31    pub base_mining_rates: [u64; 4],
32    
33    /// Minimum contribution to join auction pool (0.01 SOL = 10,000,000 lamports)
34    pub min_pool_contribution: u64,
35    
36    /// Auction duration in seconds (1 hour = 3600)
37    pub auction_duration_seconds: u64,
38    
39    /// Starting prices per well (in lamports)
40    /// Scaled to match mining rate differentiation for strategic choices:
41    /// - Well 0 (Seep): 0.1 SOL = 100,000,000 lamports (lowest price, accessible)
42    /// - Well 1 (Flow): 0.2 SOL = 200,000,000 lamports (2x Well 0)
43    /// - Well 2 (Gusher): 0.3 SOL = 300,000,000 lamports (3x Well 0)
44    /// - Well 3 (Blowout): 0.4 SOL = 400,000,000 lamports (4x Well 0)
45    pub starting_prices: [u64; 4],
46    
47    /// Buffer field (for future use)
48    pub buffer_a: Numeric,
49    
50    /// Total OIL minted from auction-based mining (in atomic units)
51    /// Used for supply-based halving: halvings occur at 1M, 2.5M, 5M, 10M, etc. OIL
52    /// Repurposed from buffer_b - maintains account layout compatibility
53    pub total_auction_oil_minted: u64,
54    
55    /// Number of halvings that have been applied (starts at 0)
56    /// Each halving reduces rates by 25% (multiply by 0.75)
57    /// Repurposed from buffer_c - maintains account layout compatibility
58    pub halving_count: u64,
59    
60    /// Buffer field (for future use)
61    pub buffer_d: u64,
62}
63
64impl Auction {
65    pub fn pda() -> (Pubkey, u8) {
66        auction_pda()
67    }
68
69    /// Get the next halving threshold based on current halving count
70    /// Halving thresholds: 1M, 2.5M, 5M, 10M, 20M, 40M, etc. (exponential)
71    /// All thresholds are in atomic units (multiply OIL amounts by ONE_OIL)
72    /// Formula: threshold = (1_000_000 * ONE_OIL) * multiplier for first 3, then doubles
73    pub fn next_halving_threshold(&self) -> u64 {
74        const ONE_MILLION_OIL: u64 = 1_000_000;
75        match self.halving_count {
76            0 => ONE_MILLION_OIL * ONE_OIL,                    // 1M OIL
77            1 => (ONE_MILLION_OIL * 25 / 10) * ONE_OIL,        // 2.5M OIL
78            2 => (ONE_MILLION_OIL * 5) * ONE_OIL,              // 5M OIL
79            3 => (ONE_MILLION_OIL * 10) * ONE_OIL,            // 10M OIL
80            n => {
81                // After 10M, double each time: 20M, 40M, 80M, etc.
82                (ONE_MILLION_OIL * 10 * (1u64 << (n - 3))) * ONE_OIL
83            }
84        }
85    }
86    
87    /// Check if halving should be applied based on total OIL minted
88    /// Returns number of halvings to apply (can be > 1 if multiple thresholds crossed)
89    pub fn should_apply_halving(&self) -> u64 {
90        let mut halvings_to_apply = 0;
91        let mut current_threshold = self.next_halving_threshold();
92        let mut current_halving_count = self.halving_count;
93        
94        // Check if we've crossed any thresholds
95        while self.total_auction_oil_minted >= current_threshold {
96            halvings_to_apply += 1;
97            current_halving_count += 1;
98            
99            // Calculate next threshold (in atomic units)
100            const ONE_MILLION_OIL: u64 = 1_000_000;
101            current_threshold = match current_halving_count {
102                0 => ONE_MILLION_OIL * ONE_OIL,                    // 1M OIL
103                1 => (ONE_MILLION_OIL * 25 / 10) * ONE_OIL,        // 2.5M OIL
104                2 => (ONE_MILLION_OIL * 5) * ONE_OIL,              // 5M OIL
105                3 => (ONE_MILLION_OIL * 10) * ONE_OIL,            // 10M OIL
106                n => (ONE_MILLION_OIL * 10 * (1u64 << (n - 3))) * ONE_OIL, // 20M, 40M, 80M, etc.
107            };
108        }
109        
110        halvings_to_apply
111    }
112}
113
114account!(OilAccount, Auction);
115