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 total_contributed: u64,
52
53 pub pool_bid_cost: u64,
57}
58
59impl Well {
60 pub fn pda(well_id: u64) -> (Pubkey, u8) {
61 well_pda(well_id)
62 }
63
64 pub fn current_price(&self, auction: &Auction, clock: &Clock) -> u64 {
65 use crate::consts::AUCTION_FLOOR_PRICE;
66
67 use solana_program::pubkey::Pubkey;
69 if self.current_bidder == Pubkey::default() {
70 return self.init_price; }
72
73 let elapsed = clock.unix_timestamp.saturating_sub(self.epoch_start_time as i64);
74 let duration = auction.auction_duration_seconds as i64;
75
76 if elapsed >= duration {
77 return AUCTION_FLOOR_PRICE; }
79
80 let remaining = duration - elapsed;
82 let price_range = self.init_price.saturating_sub(AUCTION_FLOOR_PRICE);
83 let decayed_amount = (price_range as u128 * remaining as u128 / duration as u128) as u64;
84 AUCTION_FLOOR_PRICE + decayed_amount
85 }
86
87 pub fn update_accumulated_oil(&mut self, clock: &Clock) {
88 use solana_program::pubkey::Pubkey;
90 if self.current_bidder == Pubkey::default() {
91 return;
92 }
93
94 let last_update = self.last_update_time as i64;
95 let elapsed = clock.unix_timestamp.saturating_sub(last_update);
96 if elapsed <= 0 {
97 return;
98 }
99
100 let oil_mined = self.mps
102 .checked_mul(elapsed as u64)
103 .unwrap_or(0);
104
105 self.accumulated_oil = self.accumulated_oil
106 .checked_add(oil_mined)
107 .unwrap_or(u64::MAX);
108
109 self.lifetime_oil_mined = self.lifetime_oil_mined
110 .checked_add(oil_mined)
111 .unwrap_or(u64::MAX);
112
113 self.operator_total_oil_mined = self.operator_total_oil_mined
115 .checked_add(oil_mined)
116 .unwrap_or(u64::MAX);
117
118 self.last_update_time = clock.unix_timestamp as u64;
119 }
120
121 pub fn check_and_apply_halving(&mut self, auction: &mut Auction, clock: &Clock) {
122 let current_time = clock.unix_timestamp as u64;
124 let (halvings_to_apply, is_first_halving) = auction.should_apply_halving(current_time);
125
126 if halvings_to_apply > 0 {
127 if is_first_halving {
128 self.mps = self.mps / 2; self.halving_count += 1;
131 auction.halving_count += 1;
132 auction.last_halving_time = current_time;
133 } else {
134 for _ in 0..halvings_to_apply {
136 self.mps = (self.mps * 3) / 4; self.halving_count += 1;
138 auction.halving_count += 1;
139 }
140 auction.last_halving_time = current_time;
142 }
143 }
144 }
145}
146
147account!(OilAccount, Well);
148