1use steel::*;
2
3use crate::state::{stake_pda, Treasury};
4
5use super::OreAccount;
6
7#[repr(C)]
8#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
9pub struct Stake {
10 pub authority: Pubkey,
12
13 pub balance: u64,
15
16 pub last_claim_at: i64,
18
19 pub last_deposit_at: i64,
21
22 pub last_withdraw_at: i64,
24
25 pub rewards_factor: Numeric,
27
28 pub rewards: u64,
30
31 pub lifetime_rewards: u64,
33
34 pub is_seeker: u64,
36}
37
38impl Stake {
39 pub fn pda(&self) -> (Pubkey, u8) {
40 stake_pda(self.authority)
41 }
42
43 pub fn claim(&mut self, amount: u64, clock: &Clock, treasury: &Treasury) -> u64 {
44 self.update_rewards(treasury);
45 let amount = self.rewards.min(amount);
46 self.rewards -= amount;
47 self.last_claim_at = clock.unix_timestamp;
48 amount
49 }
50
51 pub fn deposit(
52 &mut self,
53 amount: u64,
54 clock: &Clock,
55 treasury: &mut Treasury,
56 sender: &TokenAccount,
57 ) -> u64 {
58 self.update_rewards(treasury);
59 let amount = sender.amount().min(amount);
60 self.balance += amount;
61 self.last_deposit_at = clock.unix_timestamp;
62 treasury.total_staked += amount;
63 amount
64 }
65
66 pub fn withdraw(&mut self, amount: u64, clock: &Clock, treasury: &mut Treasury) -> u64 {
67 self.update_rewards(treasury);
68 let amount = self.balance.min(amount);
69 self.balance -= amount;
70 self.last_withdraw_at = clock.unix_timestamp;
71 treasury.total_staked -= amount;
72 amount
73 }
74
75 pub fn update_rewards(&mut self, treasury: &Treasury) {
76 if treasury.stake_rewards_factor > self.rewards_factor {
78 let accumulated_rewards = treasury.stake_rewards_factor - self.rewards_factor;
79 if accumulated_rewards < Numeric::ZERO {
80 panic!("Accumulated rewards is negative");
81 }
82 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.balance);
83 self.rewards += personal_rewards.to_u64();
84 self.lifetime_rewards += personal_rewards.to_u64();
85 }
86
87 self.rewards_factor = treasury.stake_rewards_factor;
89 }
90}
91
92account!(OreAccount, Stake);