1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::well_pda;
5
6use super::{OilAccount, Auction};
7
8#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct Well {
12 pub well_id: u64,
14
15 pub epoch_id: u64,
17
18 pub current_bidder: Pubkey,
20
21 pub init_price: u64,
23
24 pub mps: u64,
26
27 pub epoch_start_time: u64,
29
30 pub accumulated_oil: u64,
32
33 pub last_update_time: u64,
35
36 pub halving_count: u64,
38
39 pub lifetime_oil_mined: u64,
41
42 pub operator_total_oil_mined: u64,
44
45 pub buffer_c: u64,
47
48 pub buffer_d: u64,
50
51 pub buffer_e: u64,
53}
54
55impl Well {
56 pub fn pda(well_id: u64) -> (Pubkey, u8) {
57 well_pda(well_id)
58 }
59
60 pub fn current_price(&self, auction: &Auction, clock: &Clock) -> u64 {
62 use crate::consts::AUCTION_FLOOR_PRICE;
63
64 use solana_program::pubkey::Pubkey;
66 if self.current_bidder == Pubkey::default() {
67 return self.init_price; }
69
70 let elapsed = clock.unix_timestamp.saturating_sub(self.epoch_start_time as i64);
71 let duration = auction.auction_duration_seconds as i64;
72
73 if elapsed >= duration {
74 return AUCTION_FLOOR_PRICE; }
76
77 let remaining = duration - elapsed;
79 let price_range = self.init_price.saturating_sub(AUCTION_FLOOR_PRICE);
80 let decayed_amount = (price_range as u128 * remaining as u128 / duration as u128) as u64;
81 AUCTION_FLOOR_PRICE + decayed_amount
82 }
83
84 pub fn update_accumulated_oil(&mut self, clock: &Clock) {
86 use solana_program::pubkey::Pubkey;
88 if self.current_bidder == Pubkey::default() {
89 return;
90 }
91
92 let last_update = self.last_update_time as i64;
93 let elapsed = clock.unix_timestamp.saturating_sub(last_update);
94 if elapsed <= 0 {
95 return;
96 }
97
98 let oil_mined = self.mps
100 .checked_mul(elapsed as u64)
101 .unwrap_or(0);
102
103 self.accumulated_oil = self.accumulated_oil
104 .checked_add(oil_mined)
105 .unwrap_or(u64::MAX);
106
107 self.lifetime_oil_mined = self.lifetime_oil_mined
108 .checked_add(oil_mined)
109 .unwrap_or(u64::MAX);
110
111 self.operator_total_oil_mined = self.operator_total_oil_mined
113 .checked_add(oil_mined)
114 .unwrap_or(u64::MAX);
115
116 self.last_update_time = clock.unix_timestamp as u64;
117 }
118
119 pub fn check_and_apply_halving(&mut self, auction: &mut Auction, clock: &Clock) {
121 let current_time = clock.unix_timestamp as u64;
123 let halvings_to_apply = auction.should_apply_halving(current_time);
124
125 if halvings_to_apply > 0 {
126 for _ in 0..halvings_to_apply {
128 self.mps = self.mps / 2; self.halving_count += 1;
130 }
131
132 auction.last_halving_time = current_time;
134 }
135 }
136}
137
138account!(OilAccount, Well);
139