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