1use steel::*;
2
3use crate::state::round_pda;
4
5use super::OreAccount;
6
7#[repr(C)]
8#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
9pub struct Round {
10 pub id: u64,
12
13 pub deployed: [u64; 25],
15
16 pub slot_hash: [u8; 32],
18
19 pub count: [u64; 25],
21
22 pub expires_at: u64,
24
25 pub motherlode: u64,
27
28 pub rent_payer: Pubkey,
30
31 pub top_miner: Pubkey,
33
34 pub top_miner_reward: u64,
36
37 pub total_deployed: u64,
39
40 pub total_vaulted: u64,
42
43 pub total_winnings: u64,
45}
46
47impl Round {
48 pub fn pda(&self) -> (Pubkey, u8) {
49 round_pda(self.id)
50 }
51
52 pub fn rng(&self) -> Option<u64> {
53 if self.slot_hash == [0; 32] || self.slot_hash == [u8::MAX; 32] {
54 return None;
55 }
56 let r1 = u64::from_le_bytes(self.slot_hash[0..8].try_into().unwrap());
57 let r2 = u64::from_le_bytes(self.slot_hash[8..16].try_into().unwrap());
58 let r3 = u64::from_le_bytes(self.slot_hash[16..24].try_into().unwrap());
59 let r4 = u64::from_le_bytes(self.slot_hash[24..32].try_into().unwrap());
60 let r = r1 ^ r2 ^ r3 ^ r4;
61 Some(r)
62 }
63
64 pub fn winning_square(&self, rng: u64) -> usize {
65 (rng % 25) as usize
66 }
67
68 pub fn top_miner_sample(&self, rng: u64, winning_square: usize) -> u64 {
69 if self.deployed[winning_square] == 0 {
70 return 0;
71 }
72 rng.reverse_bits() % self.deployed[winning_square]
73 }
74
75 pub fn calculate_total_winnings(&self, winning_square: usize) -> u64 {
76 let mut total_winnings = 0;
77 for (i, &deployed) in self.deployed.iter().enumerate() {
78 if i != winning_square {
79 total_winnings += deployed;
80 }
81 }
82 total_winnings
83 }
84
85 pub fn is_split_reward(&self, rng: u64) -> bool {
86 let rng = rng.reverse_bits().to_le_bytes();
88 let r1 = u16::from_le_bytes(rng[0..2].try_into().unwrap());
89 let r2 = u16::from_le_bytes(rng[2..4].try_into().unwrap());
90 let r3 = u16::from_le_bytes(rng[4..6].try_into().unwrap());
91 let r4 = u16::from_le_bytes(rng[6..8].try_into().unwrap());
92 let r = r1 ^ r2 ^ r3 ^ r4;
93 r % 3 == 0
94 }
95
96 pub fn did_hit_motherlode(&self, rng: u64) -> bool {
97 rng.reverse_bits() % 625 == 0
98 }
99}
100
101account!(OreAccount, Round);
102
103#[cfg(test)]
104mod tests {
105 use solana_program::rent::Rent;
106
107 use super::*;
108
109 #[test]
110 fn test_rent() {
111 let size_of_round = 8 + std::mem::size_of::<Round>();
112 let required_rent = Rent::default().minimum_balance(size_of_round);
113 println!("required_rent: {}", required_rent);
114 assert!(false);
115 }
116}