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 {
61 use crate::consts::AUCTION_FLOOR_PRICE;
62
63 use solana_program::pubkey::Pubkey;
65 if self.current_bidder == Pubkey::default() {
66 return self.init_price; }
68
69 let elapsed = clock.unix_timestamp.saturating_sub(self.epoch_start_time as i64);
70 let duration = auction.auction_duration_seconds as i64;
71
72 if elapsed >= duration {
73 return AUCTION_FLOOR_PRICE; }
75
76 let remaining = duration - elapsed;
78 let price_range = self.init_price.saturating_sub(AUCTION_FLOOR_PRICE);
79 let decayed_amount = (price_range as u128 * remaining as u128 / duration as u128) as u64;
80 AUCTION_FLOOR_PRICE + decayed_amount
81 }
82
83 pub fn update_accumulated_oil(&mut self, clock: &Clock) {
84 use solana_program::pubkey::Pubkey;
86 if self.current_bidder == Pubkey::default() {
87 return;
88 }
89
90 let last_update = self.last_update_time as i64;
91 let elapsed = clock.unix_timestamp.saturating_sub(last_update);
92 if elapsed <= 0 {
93 return;
94 }
95
96 let oil_mined = self.mps
98 .checked_mul(elapsed as u64)
99 .unwrap_or(0);
100
101 self.accumulated_oil = self.accumulated_oil
102 .checked_add(oil_mined)
103 .unwrap_or(u64::MAX);
104
105 self.lifetime_oil_mined = self.lifetime_oil_mined
106 .checked_add(oil_mined)
107 .unwrap_or(u64::MAX);
108
109 self.operator_total_oil_mined = self.operator_total_oil_mined
111 .checked_add(oil_mined)
112 .unwrap_or(u64::MAX);
113
114 self.last_update_time = clock.unix_timestamp as u64;
115 }
116
117 pub fn check_and_apply_halving(&mut self, auction: &mut Auction, clock: &Clock) {
118 let current_time = clock.unix_timestamp as u64;
120 let halvings_to_apply = auction.should_apply_halving(current_time);
121
122 if halvings_to_apply > 0 {
123 for _ in 0..halvings_to_apply {
125 self.mps = self.mps / 2; self.halving_count += 1;
127 }
128
129 auction.last_halving_time = current_time;
131 }
132 }
133}
134
135account!(OilAccount, Well);
136