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