From b30cee7eb29c6cb13f0ead2229056ba37450fb6c Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Sat, 27 Apr 2024 18:06:36 +0000 Subject: [PATCH] stake --- src/error.rs | 4 ++- src/instruction.rs | 16 +++++++++ src/lib.rs | 4 +-- src/processor/claim.rs | 5 +-- src/processor/initialize.rs | 2 +- src/processor/mod.rs | 2 ++ src/processor/stake.rs | 66 +++++++++++++++++++++++++++++++++++++ src/state/treasury.rs | 3 -- 8 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/error.rs b/src/error.rs index 7bf36f4..423d18c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -17,8 +17,10 @@ pub enum OreError { BusRewardsInsufficient = 4, #[error("The claim amount cannot be greater than the claimable rewards")] ClaimTooLarge = 5, + #[error("The stake amount cannot exceed u64 size")] + StakeTooLarge = 6, #[error("The clock time is invalid")] - ClockInvalid = 6, + ClockInvalid = 7, } impl From for ProgramError { diff --git a/src/instruction.rs b/src/instruction.rs index e2555ba..c7d9bc8 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -55,6 +55,14 @@ pub enum OreInstruction { #[account(6, name = "token_program", desc = "SPL token program")] Claim = 3, + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "sender", desc = "Signer token account", writable)] + #[account(3, name = "proof", desc = "Ore proof account", writable)] + #[account(4, name = "treasury_tokens", desc = "Ore treasury token account", writable)] + #[account(5, name = "token_program", desc = "SPL token program")] + Stake = 4, + #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Admin signer", signer)] #[account(2, name = "bus_0", desc = "Ore bus account 0", writable)] @@ -123,6 +131,12 @@ pub struct ClaimArgs { pub amount: [u8; 8], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct StakeArgs { + pub amount: [u8; 8], +} + #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct UpdateAdminArgs { @@ -133,12 +147,14 @@ impl_to_bytes!(InitializeArgs); impl_to_bytes!(RegisterArgs); impl_to_bytes!(MineArgs); impl_to_bytes!(ClaimArgs); +impl_to_bytes!(StakeArgs); impl_to_bytes!(UpdateAdminArgs); impl_instruction_from_bytes!(InitializeArgs); impl_instruction_from_bytes!(RegisterArgs); impl_instruction_from_bytes!(MineArgs); impl_instruction_from_bytes!(ClaimArgs); +impl_instruction_from_bytes!(StakeArgs); impl_instruction_from_bytes!(UpdateAdminArgs); /// Builds a reset instruction. diff --git a/src/lib.rs b/src/lib.rs index 80cd215..aced536 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,9 +14,6 @@ use solana_program::{ program_error::ProgramError, pubkey::Pubkey, }; -// TODO Stake -// TODO Claim - // TODO Upgrade (v1 to v2 token) // TODO Downgrade (v2 to v1 token) @@ -43,6 +40,7 @@ pub fn process_instruction( OreInstruction::Register => process_register(program_id, accounts, data)?, OreInstruction::Mine => process_mine(program_id, accounts, data)?, OreInstruction::Claim => process_claim(program_id, accounts, data)?, + OreInstruction::Stake => process_stake(program_id, accounts, data)?, OreInstruction::Initialize => process_initialize(program_id, accounts, data)?, OreInstruction::UpdateAdmin => process_update_admin(program_id, accounts, data)?, } diff --git a/src/processor/claim.rs b/src/processor/claim.rs index 9ba5b29..9287b12 100644 --- a/src/processor/claim.rs +++ b/src/processor/claim.rs @@ -56,12 +56,9 @@ pub fn process_claim<'a, 'info>( .checked_sub(amount) .ok_or(OreError::ClaimTooLarge)?; - // Update lifetime status + // Distribute tokens from treasury to beneficiary let mut treasury_data = treasury_info.data.borrow_mut(); let treasury = Treasury::try_from_bytes_mut(&mut treasury_data)?; - treasury.total_claimed_rewards = treasury.total_claimed_rewards.saturating_add(amount); - - // Distribute tokens from treasury to beneficiary let treasury_bump = treasury.bump; drop(treasury_data); solana_program::program::invoke_signed( diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 09908b3..2e6b23f 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -148,7 +148,7 @@ pub fn process_initialize<'a, 'info>( treasury.bump = args.treasury_bump as u64; // treasury.last_reset_at = 0; // treasury.reward_rate = INITIAL_REWARD_RATE; - treasury.total_claimed_rewards = 0; + // treasury.total_claimed_rewards = 0; drop(treasury_data); // Initialize mint diff --git a/src/processor/mod.rs b/src/processor/mod.rs index e5730a0..2410f76 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -3,6 +3,7 @@ mod initialize; mod mine; mod register; mod reset; +mod stake; mod update_admin; pub use claim::*; @@ -10,4 +11,5 @@ pub use initialize::*; pub use mine::*; pub use register::*; pub use reset::*; +pub use stake::*; pub use update_admin::*; diff --git a/src/processor/stake.rs b/src/processor/stake.rs index 8b13789..e3390a3 100644 --- a/src/processor/stake.rs +++ b/src/processor/stake.rs @@ -1 +1,67 @@ +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, + program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, +}; +use crate::{ + error::OreError, instruction::StakeArgs, loaders::*, state::Proof, utils::AccountDeserialize, + MINT_ADDRESS, TREASURY_ADDRESS, +}; + +pub fn process_stake<'a, 'info>( + _program_id: &Pubkey, + accounts: &'a [AccountInfo<'info>], + data: &[u8], +) -> ProgramResult { + // Parse args + let args = StakeArgs::try_from_bytes(data)?; + let amount = u64::from_le_bytes(args.amount); + + // Load accounts + let [signer_info, sender_info, proof_info, treasury_tokens_info, token_program] = accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + load_signer(signer_info)?; + load_token_account(sender_info, Some(signer_info.key), &MINT_ADDRESS, true)?; + load_proof(proof_info, signer_info.key, true)?; + load_token_account( + treasury_tokens_info, + Some(&TREASURY_ADDRESS), + &MINT_ADDRESS, + true, + )?; + load_program(token_program, spl_token::id())?; + + // Update proof balance + let mut proof_data = proof_info.data.borrow_mut(); + let proof = Proof::try_from_bytes_mut(&mut proof_data)?; + proof.balance = proof + .balance + .checked_add(amount) + .ok_or(OreError::StakeTooLarge)?; + + // Update deposit timestamp + let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?; + proof.last_deposit_slot = clock.slot; + + // Distribute tokens from signer to treasury + solana_program::program::invoke( + &spl_token::instruction::transfer( + &spl_token::id(), + sender_info.key, + treasury_tokens_info.key, + signer_info.key, + &[signer_info.key], + amount, + )?, + &[ + token_program.clone(), + sender_info.clone(), + treasury_tokens_info.clone(), + signer_info.clone(), + ], + )?; + + Ok(()) +} diff --git a/src/state/treasury.rs b/src/state/treasury.rs index 61da711..3ae7bc2 100644 --- a/src/state/treasury.rs +++ b/src/state/treasury.rs @@ -13,9 +13,6 @@ use crate::{ pub struct Treasury { /// The bump of the treasury account PDA, for signing CPIs. pub bump: u64, - - /// The total lifetime claimed rewards of the program. - pub total_claimed_rewards: u64, } impl Discriminator for Treasury {