oil_api/state/
driller.rs

1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{driller_pda, Treasury};
5
6use super::OilAccount;
7
8
9#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct Driller {
12    /// The authority of this driller account.
13    pub authority: Pubkey,
14
15    /// The driller's prospects in the current round.
16    pub deployed: [u64; 25],
17
18    /// The cumulative amount of SOL deployed on each square prior to this driller's move.
19    pub cumulative: [u64; 25],
20
21    /// SOL witheld in reserve to pay for checkpointing.
22    pub checkpoint_fee: u64,
23
24    /// The last round that this driller checkpointed.
25    pub checkpoint_id: u64,
26
27    /// The last time this driller claimed OIL rewards.
28    pub last_claim_oil_at: i64,
29
30    /// The last time this driller claimed SOL rewards.
31    pub last_claim_sol_at: i64,
32
33    /// The rewards factor last time rewards were updated on this driller account.
34    pub rewards_factor: Numeric,
35
36    /// The amount of SOL this driller can claim.
37    pub rewards_sol: u64,
38
39    /// The amount of OIL this driller can claim.
40    pub rewards_oil: u64,
41
42    /// The amount of OIL this driller has earned from claim fees.
43    pub refined_oil: u64,
44
45    /// The ID of the round this driller last played in.
46    pub round_id: u64,
47
48    /// The total amount of SOL this driller has mined across all blocks.
49    pub lifetime_rewards_sol: u64,
50
51    /// The total amount of OIL this driller has mined across all blocks.
52    pub lifetime_rewards_oil: u64,
53
54    /// The total amount of OIL this driller has deployed across all rounds.
55    pub lifetime_deployed: u64,
56
57    /// The pubkey of the referrer who referred this driller.
58    /// If this is Pubkey::default(), the driller has no referrer (either old account or no referral used).
59    pub referrer: Pubkey,
60
61    /// The pooled deployed amount of this driller.
62    pub pooled_deployed: u64,
63}
64
65impl Driller {
66    pub fn pda(&self) -> (Pubkey, u8) {
67        driller_pda(self.authority)
68    }
69
70    pub fn claim_oil(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
71        self.update_rewards(treasury);
72        let refined_oil = self.refined_oil;
73        let rewards_oil = self.rewards_oil;
74        let mut amount = refined_oil + rewards_oil;
75        self.refined_oil = 0;
76        self.rewards_oil = 0;
77
78        // Charge a 10% fee and share with drillers who haven't claimed yet.
79        // Check total_unclaimed BEFORE subtracting this driller's rewards_oil
80        // to ensure fee is charged even if this is the only driller with unclaimed oil.
81        if treasury.total_unclaimed > 0 {
82            let fee = rewards_oil / 10;
83            amount -= fee;
84            treasury.driller_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
85            treasury.total_refined += fee;
86            self.lifetime_rewards_oil -= fee;
87        }
88        
89        treasury.total_unclaimed -= rewards_oil;
90        treasury.total_refined -= refined_oil;
91        self.last_claim_oil_at = clock.unix_timestamp;
92
93        amount
94    }
95
96    pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
97        let amount = self.rewards_sol;
98        self.rewards_sol = 0;
99        self.last_claim_sol_at = clock.unix_timestamp;
100        amount
101    }
102
103    pub fn update_rewards(&mut self, treasury: &Treasury) {
104        // Accumulate rewards, weighted by stake balance.
105        if treasury.driller_rewards_factor > self.rewards_factor {
106            let accumulated_rewards = treasury.driller_rewards_factor - self.rewards_factor;
107            if accumulated_rewards < Numeric::ZERO {
108                panic!("Accumulated rewards is negative");
109            }
110            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_oil);
111            self.refined_oil += personal_rewards.to_u64();
112            self.lifetime_rewards_oil += personal_rewards.to_u64();
113        }
114
115        // Update this driller account's last seen rewards factor.
116        self.rewards_factor = treasury.driller_rewards_factor;
117    }
118}
119
120account!(OilAccount, Driller);