1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{stake_pda, Treasury};
5
6use super::OreAccount;
7
8#[repr(C)]
9#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
10pub struct Stake {
11 pub authority: Pubkey,
13
14 pub balance: u64,
16
17 pub buffer_a: u64,
19
20 pub buffer_b: u64,
22
23 pub buffer_c: u64,
25
26 pub buffer_d: u64,
28
29 pub buffer_e: u64,
31
32 pub last_claim_at: i64,
34
35 pub last_deposit_at: i64,
37
38 pub last_withdraw_at: i64,
40
41 pub rewards_factor: Numeric,
43
44 pub rewards: u64,
46
47 pub lifetime_rewards: u64,
49
50 pub buffer_f: u64,
52}
53
54impl Stake {
55 pub fn pda(&self) -> (Pubkey, u8) {
56 stake_pda(self.authority)
57 }
58
59 pub fn claim(&mut self, amount: u64, clock: &Clock, treasury: &Treasury) -> u64 {
60 self.update_rewards(treasury);
61 let amount = self.rewards.min(amount);
62 self.rewards -= amount;
63 self.last_claim_at = clock.unix_timestamp;
64 amount
65 }
66
67 pub fn deposit(
68 &mut self,
69 amount: u64,
70 clock: &Clock,
71 treasury: &mut Treasury,
72 sender: &TokenAccount,
73 ) -> u64 {
74 self.update_rewards(treasury);
75 let amount = sender.amount().min(amount);
76 self.balance += amount;
77 self.last_deposit_at = clock.unix_timestamp;
78 treasury.total_staked += amount;
79 amount
80 }
81
82 pub fn withdraw(&mut self, amount: u64, clock: &Clock, treasury: &mut Treasury) -> u64 {
83 self.update_rewards(treasury);
84 let amount = self.balance.min(amount);
85 self.balance -= amount;
86 self.last_withdraw_at = clock.unix_timestamp;
87 treasury.total_staked -= amount;
88 amount
89 }
90
91 pub fn update_rewards(&mut self, treasury: &Treasury) {
92 if treasury.stake_rewards_factor > self.rewards_factor {
94 let accumulated_rewards = treasury.stake_rewards_factor - self.rewards_factor;
95 if accumulated_rewards < Numeric::ZERO {
96 panic!("Accumulated rewards is negative");
97 }
98 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.balance);
99 self.rewards += personal_rewards.to_u64();
100 self.lifetime_rewards += personal_rewards.to_u64();
101 }
102
103 self.rewards_factor = treasury.stake_rewards_factor;
105 }
106}
107
108account!(OreAccount, Stake);