ore_api/state/
miner.rs

1use steel::*;
2
3use crate::state::{miner_pda, Treasury};
4
5use super::OreAccount;
6
7#[repr(C)]
8#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
9pub struct Miner {
10    /// The authority of this miner account.
11    pub authority: Pubkey,
12
13    /// The miner's prospects in the current round.
14    pub deployed: [u64; 25],
15
16    /// The cumulative amount of SOL deployed on each square prior to this miner's move.
17    pub cumulative: [u64; 25],
18
19    /// SOL witheld in reserve to pay for checkpointing.
20    pub checkpoint_fee: u64,
21
22    /// The last round that this miner checkpointed.
23    pub checkpoint_id: u64,
24
25    /// The last time this miner claimed ORE rewards.
26    pub last_claim_ore_at: i64,
27
28    /// The last time this miner claimed SOL rewards.
29    pub last_claim_sol_at: i64,
30
31    /// The rewards factor last time rewards were updated on this miner account.
32    pub rewards_factor: Numeric,
33
34    /// The amount of SOL this miner can claim.
35    pub rewards_sol: u64,
36
37    /// The amount of ORE this miner can claim.
38    pub rewards_ore: u64,
39
40    /// The amount of ORE this miner has earned from claim fees.
41    pub refined_ore: u64,
42
43    /// The ID of the round this miner last played in.
44    pub round_id: u64,
45
46    /// The total amount of SOL this miner has mined across all blocks.
47    pub lifetime_rewards_sol: u64,
48
49    /// The total amount of ORE this miner has mined across all blocks.
50    pub lifetime_rewards_ore: u64,
51}
52
53impl Miner {
54    pub fn pda(&self) -> (Pubkey, u8) {
55        miner_pda(self.authority)
56    }
57
58    pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
59        self.update_rewards(treasury);
60        let refined_ore = self.refined_ore;
61        let rewards_ore = self.rewards_ore;
62        let mut amount = refined_ore + rewards_ore;
63        self.refined_ore = 0;
64        self.rewards_ore = 0;
65        treasury.total_unclaimed -= rewards_ore;
66        treasury.total_refined -= refined_ore;
67        self.last_claim_ore_at = clock.unix_timestamp;
68
69        // Charge a 10% fee and share with miners who haven't claimed yet.
70        if treasury.total_unclaimed > 0 {
71            let fee = rewards_ore / 10;
72            amount -= fee;
73            treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
74            treasury.total_refined += fee;
75            self.lifetime_rewards_ore -= fee;
76        }
77
78        amount
79    }
80
81    pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
82        let amount = self.rewards_sol;
83        self.rewards_sol = 0;
84        self.last_claim_sol_at = clock.unix_timestamp;
85        amount
86    }
87
88    pub fn update_rewards(&mut self, treasury: &Treasury) {
89        // Accumulate rewards, weighted by stake balance.
90        if treasury.miner_rewards_factor > self.rewards_factor {
91            let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
92            if accumulated_rewards < Numeric::ZERO {
93                panic!("Accumulated rewards is negative");
94            }
95            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
96            self.refined_ore += personal_rewards.to_u64();
97            self.lifetime_rewards_ore += personal_rewards.to_u64();
98        }
99
100        // Update this miner account's last seen rewards factor.
101        self.rewards_factor = treasury.miner_rewards_factor;
102    }
103}
104
105account!(OreAccount, Miner);