1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{round_pda, OreAccount};
5
6#[repr(C)]
7#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
8pub struct Round {
9 pub id: u64,
11
12 pub deployed: [u64; 25],
15
16 pub mass: [u64; 25],
18
19 pub count: [u64; 25],
22
23 pub slot_hash: [u8; 32],
26
27 pub expires_at: u64,
30
31 pub motherlode: u64,
33
34 pub rent_payer: Pubkey,
36
37 pub rewards: [u64; 25],
39
40 pub total_vaulted: u64,
43
44 pub total_winnings: u64,
47
48 pub total_miners: u64,
51
52 pub top_miner: Pubkey,
55}
56
57impl Round {
58 pub fn pda(&self) -> (Pubkey, u8) {
59 round_pda(self.id)
60 }
61
62 pub fn rng(&self) -> Option<u64> {
63 if self.slot_hash == [0; 32] || self.slot_hash == [u8::MAX; 32] {
64 return None;
65 }
66 let r1 = u64::from_le_bytes(self.slot_hash[0..8].try_into().unwrap());
67 let r2 = u64::from_le_bytes(self.slot_hash[8..16].try_into().unwrap());
68 let r3 = u64::from_le_bytes(self.slot_hash[16..24].try_into().unwrap());
69 let r4 = u64::from_le_bytes(self.slot_hash[24..32].try_into().unwrap());
70 let r = r1 ^ r2 ^ r3 ^ r4;
71 Some(r)
72 }
73
74 pub fn winning_square(&self, rng: u64) -> usize {
75 (rng % 25) as usize
76 }
77
78 pub fn top_miner_sample(&self, rng: u64, winning_square: usize) -> u64 {
79 if self.deployed[winning_square] == 0 {
80 return 0;
81 }
82 rng.reverse_bits() % self.deployed[winning_square]
83 }
84
85 pub fn calculate_total_winnings(&self, winning_square: usize) -> u64 {
86 let mut total_winnings = 0;
87 for (i, &deployed) in self.deployed.iter().enumerate() {
88 if i != winning_square {
89 total_winnings += deployed;
90 }
91 }
92 total_winnings
93 }
94
95 pub fn is_split_reward(&self, rng: u64) -> bool {
96 let rng = rng.reverse_bits().to_le_bytes();
98 let r1 = u16::from_le_bytes(rng[0..2].try_into().unwrap());
99 let r2 = u16::from_le_bytes(rng[2..4].try_into().unwrap());
100 let r3 = u16::from_le_bytes(rng[4..6].try_into().unwrap());
101 let r4 = u16::from_le_bytes(rng[6..8].try_into().unwrap());
102 let r = r1 ^ r2 ^ r3 ^ r4;
103 r % 2 == 0
104 }
105
106 pub fn did_hit_motherlode(&self, rng: u64) -> bool {
107 rng.reverse_bits() % 625 == 0
108 }
109
110 pub fn total_deployed(&self) -> u64 {
111 self.deployed.iter().sum()
112 }
113
114 pub fn top_miner_reward(&self) -> u64 {
115 self.rewards.iter().sum()
116 }
117}
118
119account!(OreAccount, Round);