use ore_api::state::Proof;
use steel::*;
use super::{Boost, BoostAccount, Config};
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct Stake {
pub authority: Pubkey,
pub balance: u64,
pub boost: Pubkey,
pub last_claim_at: i64,
pub last_deposit_at: i64,
pub last_withdraw_at: i64,
pub last_rewards_factor: Numeric,
pub rewards: u64,
pub _buffer: [u8; 1024],
}
impl Stake {
pub fn claim(
&mut self,
amount: u64,
boost: &mut Boost,
clock: &Clock,
config: &mut Config,
proof: &Proof,
) -> u64 {
self.collect_rewards(boost, config, &proof);
let amount = amount.min(self.rewards);
self.last_claim_at = clock.unix_timestamp;
self.rewards -= amount;
amount
}
pub fn deposit(
&mut self,
amount: u64,
boost: &mut Boost,
clock: &Clock,
config: &mut Config,
proof: &Proof,
sender: &TokenAccount,
) -> u64 {
self.collect_rewards(boost, config, &proof);
let amount = amount.min(sender.amount());
self.balance += amount;
self.last_deposit_at = clock.unix_timestamp;
boost.total_deposits += amount;
amount
}
pub fn withdraw(
&mut self,
amount: u64,
boost: &mut Boost,
clock: &Clock,
config: &mut Config,
proof: &Proof,
) -> u64 {
self.collect_rewards(boost, config, &proof);
let amount = amount.min(self.balance);
self.balance -= amount;
self.last_withdraw_at = clock.unix_timestamp;
boost.total_deposits -= amount;
amount
}
fn collect_rewards(&mut self, boost: &mut Boost, config: &mut Config, proof: &Proof) {
boost.collect_rewards(config, proof);
if boost.rewards_factor > self.last_rewards_factor {
let accumulated_rewards = boost.rewards_factor - self.last_rewards_factor;
if accumulated_rewards < Numeric::ZERO {
panic!("Accumulated rewards is negative");
}
let personal_rewards = accumulated_rewards * Numeric::from_u64(self.balance);
self.rewards += personal_rewards.to_u64();
}
self.last_rewards_factor = boost.rewards_factor;
}
}
account!(BoostAccount, Stake);