diff --git a/src/builders.rs b/src/builders.rs new file mode 100644 index 0000000..9e0508a --- /dev/null +++ b/src/builders.rs @@ -0,0 +1,275 @@ +use solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, sysvar, +}; + +use crate::{ + instruction::{ + ClaimArgs, InitializeArgs, MineArgs, OreInstruction, PauseArgs, RegisterArgs, StakeArgs, + UpdateAdminArgs, UpdateToleranceArgs, + }, + BUS, BUS_ADDRESSES, CONFIG, CONFIG_ADDRESS, METADATA, MINT, MINT_ADDRESS, MINT_NOISE, PROOF, + TREASURY, TREASURY_ADDRESS, +}; + +/// Builds a reset instruction. +pub fn reset(signer: Pubkey) -> Instruction { + let treasury_tokens = spl_associated_token_account::get_associated_token_address( + &TREASURY_ADDRESS, + &MINT_ADDRESS, + ); + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(BUS_ADDRESSES[0], false), + AccountMeta::new(BUS_ADDRESSES[1], false), + AccountMeta::new(BUS_ADDRESSES[2], false), + AccountMeta::new(BUS_ADDRESSES[3], false), + AccountMeta::new(BUS_ADDRESSES[4], false), + AccountMeta::new(BUS_ADDRESSES[5], false), + AccountMeta::new(BUS_ADDRESSES[6], false), + AccountMeta::new(BUS_ADDRESSES[7], false), + AccountMeta::new(CONFIG_ADDRESS, false), + AccountMeta::new(MINT_ADDRESS, false), + AccountMeta::new(TREASURY_ADDRESS, false), + AccountMeta::new(treasury_tokens, false), + AccountMeta::new_readonly(spl_token::id(), false), + ], + data: OreInstruction::Reset.to_vec(), + } +} + +/// Builds a register instruction. +pub fn register(signer: Pubkey) -> Instruction { + let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()); + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(proof_pda.0, false), + AccountMeta::new_readonly(solana_program::system_program::id(), false), + AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), + ], + data: [ + OreInstruction::Register.to_vec(), + RegisterArgs { bump: proof_pda.1 }.to_bytes().to_vec(), + ] + .concat(), + } +} + +/// Builds a mine instruction. +pub fn mine(signer: Pubkey, bus: Pubkey, nonce: u64) -> Instruction { + let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(bus, false), + AccountMeta::new_readonly(CONFIG_ADDRESS, false), + AccountMeta::new(proof, false), + AccountMeta::new_readonly(sysvar::instructions::id(), false), + AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), + ], + data: [ + OreInstruction::Mine.to_vec(), + MineArgs { + nonce: nonce.to_le_bytes(), + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} + +/// Builds a claim instruction. +pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction { + let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; + let treasury_tokens = spl_associated_token_account::get_associated_token_address( + &TREASURY_ADDRESS, + &MINT_ADDRESS, + ); + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(beneficiary, false), + AccountMeta::new(proof, false), + AccountMeta::new_readonly(TREASURY_ADDRESS, false), + AccountMeta::new(treasury_tokens, false), + AccountMeta::new_readonly(spl_token::id(), false), + ], + data: [ + OreInstruction::Claim.to_vec(), + ClaimArgs { + amount: amount.to_le_bytes(), + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} + +/// Build a stake instruction. +pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction { + let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; + let treasury_tokens = spl_associated_token_account::get_associated_token_address( + &TREASURY_ADDRESS, + &MINT_ADDRESS, + ); + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(proof, false), + AccountMeta::new(sender, false), + AccountMeta::new(treasury_tokens, false), + AccountMeta::new_readonly(spl_token::id(), false), + ], + data: [ + OreInstruction::Stake.to_vec(), + StakeArgs { + amount: amount.to_le_bytes(), + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} + +/// Builds an initialize instruction. +pub fn initialize(signer: Pubkey) -> Instruction { + let bus_pdas = [ + Pubkey::find_program_address(&[BUS, &[0]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[1]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[2]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[3]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[4]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[5]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[6]], &crate::id()), + Pubkey::find_program_address(&[BUS, &[7]], &crate::id()), + ]; + let config_pda = Pubkey::find_program_address(&[CONFIG], &crate::id()); + let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::id()); + let treasury_pda = Pubkey::find_program_address(&[TREASURY], &crate::id()); + let treasury_tokens = + spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0); + let metadata_pda = Pubkey::find_program_address( + &[ + METADATA, + mpl_token_metadata::ID.as_ref(), + mint_pda.0.as_ref(), + ], + &mpl_token_metadata::ID, + ); + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(bus_pdas[0].0, false), + AccountMeta::new(bus_pdas[1].0, false), + AccountMeta::new(bus_pdas[2].0, false), + AccountMeta::new(bus_pdas[3].0, false), + AccountMeta::new(bus_pdas[4].0, false), + AccountMeta::new(bus_pdas[5].0, false), + AccountMeta::new(bus_pdas[6].0, false), + AccountMeta::new(bus_pdas[7].0, false), + AccountMeta::new(config_pda.0, false), + AccountMeta::new(metadata_pda.0, false), + AccountMeta::new(mint_pda.0, false), + AccountMeta::new(treasury_pda.0, false), + AccountMeta::new(treasury_tokens, false), + AccountMeta::new_readonly(system_program::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(spl_associated_token_account::id(), false), + // AccountMeta::new_readonly(mpl_token_metadata::ID, false), + AccountMeta::new_readonly(sysvar::rent::id(), false), + ], + data: [ + OreInstruction::Initialize.to_vec(), + InitializeArgs { + bus_0_bump: bus_pdas[0].1, + bus_1_bump: bus_pdas[1].1, + bus_2_bump: bus_pdas[2].1, + bus_3_bump: bus_pdas[3].1, + bus_4_bump: bus_pdas[4].1, + bus_5_bump: bus_pdas[5].1, + bus_6_bump: bus_pdas[6].1, + bus_7_bump: bus_pdas[7].1, + config_bump: config_pda.1, + metadata_bump: metadata_pda.1, + mint_bump: mint_pda.1, + treasury_bump: treasury_pda.1, + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} + +/// Build an update_admin instruction. +pub fn update_admin(signer: Pubkey, new_admin: Pubkey) -> Instruction { + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(CONFIG_ADDRESS, false), + ], + data: [ + OreInstruction::UpdateAdmin.to_vec(), + UpdateAdminArgs { new_admin }.to_bytes().to_vec(), + ] + .concat(), + } +} + +/// Build an update_tolerance instruction. +pub fn update_tolerance( + signer: Pubkey, + new_liveness_tolerance: u64, + new_spam_tolerance: u64, +) -> Instruction { + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(CONFIG_ADDRESS, false), + ], + data: [ + OreInstruction::UpdateTolerance.to_vec(), + UpdateToleranceArgs { + tolerance_liveness: new_liveness_tolerance, + tolerance_spam: new_spam_tolerance, + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} + +/// Build a pause instruction. +pub fn pause(signer: Pubkey, paused: bool) -> Instruction { + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(CONFIG_ADDRESS, false), + ], + data: [ + OreInstruction::UpdateAdmin.to_vec(), + PauseArgs { + paused: paused as u8, + } + .to_bytes() + .to_vec(), + ] + .concat(), + } +} diff --git a/src/consts.rs b/src/consts.rs index c95453e..71a12a9 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -77,10 +77,6 @@ pub const METADATA_SYMBOL: &str = "ORE"; /// The uri for token metdata. pub const METADATA_URI: &str = "https://ore.supply/metadata.json"; -/// Program id of the compute budge program. -pub const COMPUTE_BUDGET_PROGRAM_ID: Pubkey = - pubkey!("ComputeBudget111111111111111111111111111111"); - /// Program id for const pda derivations const PROGRAM_ID: [u8; 32] = unsafe { *(&crate::id() as *const Pubkey as *const [u8; 32]) }; diff --git a/src/instruction.rs b/src/instruction.rs index 340bff6..6c81123 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,16 +1,9 @@ use bytemuck::{Pod, Zeroable}; use num_enum::TryFromPrimitive; use shank::ShankInstruction; -use solana_program::{ - instruction::{AccountMeta, Instruction}, - pubkey::Pubkey, - system_program, sysvar, -}; +use solana_program::pubkey::Pubkey; -use crate::{ - impl_instruction_from_bytes, impl_to_bytes, BUS, BUS_ADDRESSES, CONFIG, CONFIG_ADDRESS, - METADATA, MINT, MINT_ADDRESS, MINT_NOISE, PROOF, TREASURY, TREASURY_ADDRESS, -}; +use crate::{impl_instruction_from_bytes, impl_to_bytes}; #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ShankInstruction, TryFromPrimitive)] @@ -210,264 +203,3 @@ impl_instruction_from_bytes!(UpgradeArgs); impl_instruction_from_bytes!(UpdateAdminArgs); impl_instruction_from_bytes!(UpdateToleranceArgs); impl_instruction_from_bytes!(PauseArgs); - -/// Builds a reset instruction. -pub fn reset(signer: Pubkey) -> Instruction { - let treasury_tokens = spl_associated_token_account::get_associated_token_address( - &TREASURY_ADDRESS, - &MINT_ADDRESS, - ); - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(BUS_ADDRESSES[0], false), - AccountMeta::new(BUS_ADDRESSES[1], false), - AccountMeta::new(BUS_ADDRESSES[2], false), - AccountMeta::new(BUS_ADDRESSES[3], false), - AccountMeta::new(BUS_ADDRESSES[4], false), - AccountMeta::new(BUS_ADDRESSES[5], false), - AccountMeta::new(BUS_ADDRESSES[6], false), - AccountMeta::new(BUS_ADDRESSES[7], false), - AccountMeta::new(CONFIG_ADDRESS, false), - AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(TREASURY_ADDRESS, false), - AccountMeta::new(treasury_tokens, false), - AccountMeta::new_readonly(spl_token::id(), false), - ], - data: OreInstruction::Reset.to_vec(), - } -} - -/// Builds a register instruction. -pub fn register(signer: Pubkey) -> Instruction { - let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()); - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(proof_pda.0, false), - AccountMeta::new_readonly(solana_program::system_program::id(), false), - AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), - ], - data: [ - OreInstruction::Register.to_vec(), - RegisterArgs { bump: proof_pda.1 }.to_bytes().to_vec(), - ] - .concat(), - } -} - -/// Builds a mine instruction. -pub fn mine(signer: Pubkey, bus: Pubkey, nonce: u64) -> Instruction { - let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(bus, false), - AccountMeta::new_readonly(CONFIG_ADDRESS, false), - AccountMeta::new(proof, false), - AccountMeta::new_readonly(sysvar::instructions::id(), false), - AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), - ], - data: [ - OreInstruction::Mine.to_vec(), - MineArgs { - nonce: nonce.to_le_bytes(), - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Builds a claim instruction. -pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction { - let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; - let treasury_tokens = spl_associated_token_account::get_associated_token_address( - &TREASURY_ADDRESS, - &MINT_ADDRESS, - ); - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(beneficiary, false), - AccountMeta::new(proof, false), - AccountMeta::new_readonly(TREASURY_ADDRESS, false), - AccountMeta::new(treasury_tokens, false), - AccountMeta::new_readonly(spl_token::id(), false), - ], - data: [ - OreInstruction::Claim.to_vec(), - ClaimArgs { - amount: amount.to_le_bytes(), - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Build a stake instruction. -pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction { - let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; - let treasury_tokens = spl_associated_token_account::get_associated_token_address( - &TREASURY_ADDRESS, - &MINT_ADDRESS, - ); - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(proof, false), - AccountMeta::new(sender, false), - AccountMeta::new(treasury_tokens, false), - AccountMeta::new_readonly(spl_token::id(), false), - ], - data: [ - OreInstruction::Stake.to_vec(), - StakeArgs { - amount: amount.to_le_bytes(), - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Builds an initialize instruction. -pub fn initialize(signer: Pubkey) -> Instruction { - let bus_pdas = [ - Pubkey::find_program_address(&[BUS, &[0]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[1]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[2]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[3]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[4]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[5]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[6]], &crate::id()), - Pubkey::find_program_address(&[BUS, &[7]], &crate::id()), - ]; - let config_pda = Pubkey::find_program_address(&[CONFIG], &crate::id()); - let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::id()); - let treasury_pda = Pubkey::find_program_address(&[TREASURY], &crate::id()); - let treasury_tokens = - spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0); - let metadata_pda = Pubkey::find_program_address( - &[ - METADATA, - mpl_token_metadata::ID.as_ref(), - mint_pda.0.as_ref(), - ], - &mpl_token_metadata::ID, - ); - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(bus_pdas[0].0, false), - AccountMeta::new(bus_pdas[1].0, false), - AccountMeta::new(bus_pdas[2].0, false), - AccountMeta::new(bus_pdas[3].0, false), - AccountMeta::new(bus_pdas[4].0, false), - AccountMeta::new(bus_pdas[5].0, false), - AccountMeta::new(bus_pdas[6].0, false), - AccountMeta::new(bus_pdas[7].0, false), - AccountMeta::new(config_pda.0, false), - AccountMeta::new(metadata_pda.0, false), - AccountMeta::new(mint_pda.0, false), - AccountMeta::new(treasury_pda.0, false), - AccountMeta::new(treasury_tokens, false), - AccountMeta::new_readonly(system_program::id(), false), - AccountMeta::new_readonly(spl_token::id(), false), - AccountMeta::new_readonly(spl_associated_token_account::id(), false), - // AccountMeta::new_readonly(mpl_token_metadata::ID, false), - AccountMeta::new_readonly(sysvar::rent::id(), false), - ], - data: [ - OreInstruction::Initialize.to_vec(), - InitializeArgs { - bus_0_bump: bus_pdas[0].1, - bus_1_bump: bus_pdas[1].1, - bus_2_bump: bus_pdas[2].1, - bus_3_bump: bus_pdas[3].1, - bus_4_bump: bus_pdas[4].1, - bus_5_bump: bus_pdas[5].1, - bus_6_bump: bus_pdas[6].1, - bus_7_bump: bus_pdas[7].1, - config_bump: config_pda.1, - metadata_bump: metadata_pda.1, - mint_bump: mint_pda.1, - treasury_bump: treasury_pda.1, - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Build an update_admin instruction. -pub fn update_admin(signer: Pubkey, new_admin: Pubkey) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateAdmin.to_vec(), - UpdateAdminArgs { new_admin }.to_bytes().to_vec(), - ] - .concat(), - } -} - -/// Build an update_tolerance instruction. -pub fn update_tolerance( - signer: Pubkey, - new_liveness_tolerance: u64, - new_spam_tolerance: u64, -) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateTolerance.to_vec(), - UpdateToleranceArgs { - tolerance_liveness: new_liveness_tolerance, - tolerance_spam: new_spam_tolerance, - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Build a pause instruction. -pub fn pause(signer: Pubkey, paused: bool) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateAdmin.to_vec(), - PauseArgs { - paused: paused as u8, - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} diff --git a/src/lib.rs b/src/lib.rs index fc29e90..4050f87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +pub mod builders; pub mod consts; pub mod error; pub mod instruction; @@ -14,7 +15,6 @@ use solana_program::{ program_error::ProgramError, pubkey::Pubkey, }; -// TODO Close proof accounts to recover sol // TODO Is downgrade necessary? declare_id!("mineRHF5r6S7HyD9SppBfVMXMavDkJsxwGesEvxZr2A"); @@ -36,13 +36,13 @@ pub fn process_instruction( .ok_or(ProgramError::InvalidInstructionData)?; match OreInstruction::try_from(*tag).or(Err(ProgramError::InvalidInstructionData))? { - OreInstruction::Reset => process_reset(program_id, accounts, data)?, OreInstruction::Register => process_register(program_id, accounts, data)?, + OreInstruction::Deregister => process_deregister(program_id, accounts, data)?, + OreInstruction::Reset => process_reset(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::Upgrade => process_upgrade(program_id, accounts, data)?, - OreInstruction::Deregister => process_deregister(program_id, accounts, data)?, OreInstruction::Initialize => process_initialize(program_id, accounts, data)?, OreInstruction::UpdateAdmin => process_update_admin(program_id, accounts, data)?, OreInstruction::UpdateTolerance => process_update_tolerance(program_id, accounts, data)?, diff --git a/src/processor/deregister.rs b/src/processor/deregister.rs index 6d6c881..0640e6c 100644 --- a/src/processor/deregister.rs +++ b/src/processor/deregister.rs @@ -1,23 +1,14 @@ use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, - pubkey::Pubkey, system_program, + account_info::AccountInfo, entrypoint::ProgramResult, program::invoke_signed, + program_error::ProgramError, pubkey::Pubkey, system_program, }; -use crate::{instruction::RegisterArgs, loaders::*}; +use crate::{loaders::*, state::Proof, utils::AccountDeserialize, PROOF}; -/// Register generates a new hash chain for a prospective miner. Its responsibilities include: -/// 1. Initialize a new proof account. -/// 2. Generate an initial hash from the signer's key. -/// -/// Safety requirements: -/// - Register is a permissionless instruction and can be invoked by any singer. -/// - Can only succeed if the provided proof acount PDA is valid (associated with the signer). -/// - Can only succeed once per signer. -/// - The provided system program must be valid. pub fn process_deregister<'a, 'info>( _program_id: &Pubkey, accounts: &'a [AccountInfo<'info>], - data: &[u8], + _data: &[u8], ) -> ProgramResult { // Load accounts let [signer, proof_info, system_program] = accounts else { @@ -27,10 +18,37 @@ pub fn process_deregister<'a, 'info>( load_proof(proof_info, signer.key, true)?; load_program(system_program, system_program::id())?; - // TODO Ensure proof.balance == 0 - // TODO Send lamports to signer - // TODO Realloc data to 0 - // TODO Reassign back to system program + // Validate balance is zero + let proof_data = proof_info.data.borrow(); + let proof = Proof::try_from_bytes(&proof_data)?; + if proof.balance.gt(&0) { + return Err(ProgramError::InvalidAccountData); + } + + // Generate bump + let bump = Pubkey::find_program_address(&[PROOF, signer.key.as_ref()], &crate::id()).1; + + // Realloc data to zero + drop(proof_data); + proof_info.realloc(0, false)?; + + // Send lamports to signer + invoke_signed( + &solana_program::system_instruction::transfer( + proof_info.key, + signer.key, + proof_info.lamports(), + ), + &[proof_info.clone(), signer.clone(), system_program.clone()], + &[&[PROOF, signer.key.as_ref(), &[bump]]], + )?; + + // Reassign back to system program + solana_program::program::invoke_signed( + &solana_program::system_instruction::assign(proof_info.key, &system_program::id()), + &[proof_info.clone(), system_program.clone()], + &[&[PROOF, signer.key.as_ref(), &[bump]]], + )?; Ok(()) } diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 85c424a..f387eed 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -179,6 +179,7 @@ pub fn process_initialize<'a, 'info>( &[&[MINT, MINT_NOISE.as_slice(), &[args.mint_bump]]], )?; + // TODO Fix metadata initialization // Initialize mint metadata // mpl_token_metadata::instructions::CreateMetadataAccountV3Cpi { // __program: metadata_program, diff --git a/src/processor/mine.rs b/src/processor/mine.rs index 69916b8..a0d168f 100644 --- a/src/processor/mine.rs +++ b/src/processor/mine.rs @@ -14,6 +14,7 @@ use solana_program::{ slot_hashes::SlotHash, sysvar::{self, instructions::load_current_index, Sysvar}, }; +use solana_program::{program::set_return_data, pubkey}; use crate::{ error::OreError, @@ -21,7 +22,7 @@ use crate::{ loaders::*, state::{Bus, Config, Proof}, utils::AccountDeserialize, - COMPUTE_BUDGET_PROGRAM_ID, MIN_DIFFICULTY, ONE_MINUTE, TWO_YEARS, + MIN_DIFFICULTY, ONE_MINUTE, TWO_YEARS, }; /// Mine is the primary workhorse instruction of the Ore program. Its responsibilities include: @@ -118,23 +119,22 @@ pub fn process_mine<'a, 'info>( sol_log(&format!("Staking {}", staking_reward)); } - // Apply spam/liveness penalty + // Apply spam penalty let t = clock.unix_timestamp; let t_target = proof.last_hash_at.saturating_add(ONE_MINUTE); let t_spam = t_target.saturating_sub(config.tolerance_spam); - let t_liveness = t_target.saturating_add(config.tolerance_liveness); if t.lt(&t_spam) { reward = 0; sol_log("Spam penalty"); - } else if t.gt(&t_liveness) { + } + + // Apply liveness penalty + let t_liveness = t_target.saturating_add(config.tolerance_liveness); + if t.gt(&t_liveness) { reward = reward.saturating_sub( reward .saturating_mul(t.saturating_sub(t_liveness) as u64) - .saturating_div( - t_target - .saturating_add(ONE_MINUTE) - .saturating_sub(t_liveness) as u64, - ), + .saturating_div(ONE_MINUTE as u64), ); sol_log(&format!( "Liveness penalty ({} sec) {}", @@ -174,7 +174,7 @@ pub fn process_mine<'a, 'info>( proof.total_rewards = proof.total_rewards.saturating_add(reward); // Log the mined rewards - // set_return_data(reward.to_le_bytes().as_slice()); + set_return_data(reward_actual.to_le_bytes().as_slice()); Ok(()) } @@ -222,3 +222,6 @@ fn validate_transaction(msg: &[u8]) -> Result { Ok(true) } + +/// Program id of the compute budge program. +const COMPUTE_BUDGET_PROGRAM_ID: Pubkey = pubkey!("ComputeBudget111111111111111111111111111111"); diff --git a/src/processor/stake.rs b/src/processor/stake.rs index 008a815..dc18c61 100644 --- a/src/processor/stake.rs +++ b/src/processor/stake.rs @@ -18,13 +18,12 @@ pub fn process_stake<'a, 'info>( let amount = u64::from_le_bytes(args.amount); // Load accounts - let [signer_info, proof_info, sender_info, treasury_tokens_info, token_program] = accounts - else { + let [signer, proof_info, sender_info, treasury_tokens_info, token_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; - load_signer(signer_info)?; - load_proof(proof_info, signer_info.key, true)?; - load_token_account(sender_info, Some(signer_info.key), &MINT_ADDRESS, true)?; + load_signer(signer)?; + load_proof(proof_info, signer.key, true)?; + load_token_account(sender_info, Some(signer.key), &MINT_ADDRESS, true)?; load_token_account( treasury_tokens_info, Some(&TREASURY_ADDRESS), @@ -48,15 +47,15 @@ pub fn process_stake<'a, 'info>( &spl_token::id(), sender_info.key, treasury_tokens_info.key, - signer_info.key, - &[signer_info.key], + signer.key, + &[signer.key], amount, )?, &[ token_program.clone(), sender_info.clone(), treasury_tokens_info.clone(), - signer_info.clone(), + signer.clone(), ], )?; diff --git a/src/processor/upgrade.rs b/src/processor/upgrade.rs index 4c149f8..b4ee4cf 100644 --- a/src/processor/upgrade.rs +++ b/src/processor/upgrade.rs @@ -4,8 +4,7 @@ use solana_program::{ }; use crate::{ - instruction::StakeArgs, loaders::*, state::Treasury, utils::AccountDeserialize, MINT_ADDRESS, - MINT_V1_ADDRESS, TREASURY, + instruction::StakeArgs, loaders::*, MINT_ADDRESS, MINT_V1_ADDRESS, TREASURY, TREASURY_BUMP, }; pub fn process_upgrade<'a, 'info>( @@ -18,21 +17,16 @@ pub fn process_upgrade<'a, 'info>( let amount = u64::from_le_bytes(args.amount); // Load accounts - let [signer_info, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] = + let [signer, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; - load_signer(signer_info)?; - load_token_account( - beneficiary_info, - Some(&signer_info.key), - &MINT_ADDRESS, - true, - )?; + load_signer(signer)?; + load_token_account(beneficiary_info, Some(&signer.key), &MINT_ADDRESS, true)?; load_mint(mint_info, MINT_ADDRESS, true)?; load_mint(mint_v1_info, MINT_V1_ADDRESS, true)?; - load_token_account(sender_info, Some(signer_info.key), &MINT_V1_ADDRESS, true)?; + load_token_account(sender_info, Some(signer.key), &MINT_V1_ADDRESS, true)?; load_program(token_program, spl_token::id())?; // Burn v1 tokens @@ -41,15 +35,15 @@ pub fn process_upgrade<'a, 'info>( &spl_token::id(), sender_info.key, mint_v1_info.key, - signer_info.key, - &[signer_info.key], + signer.key, + &[signer.key], amount, )?, &[ token_program.clone(), sender_info.clone(), mint_v1_info.clone(), - signer_info.clone(), + signer.clone(), ], )?; @@ -58,10 +52,6 @@ pub fn process_upgrade<'a, 'info>( let amount_to_mint = amount.saturating_mul(100); // Mint to the beneficiary account - let treasury_data = treasury_info.data.borrow(); - let treasury = Treasury::try_from_bytes(&treasury_data)?; - let treasury_bump = treasury.bump as u8; - drop(treasury_data); solana_program::program::invoke_signed( &spl_token::instruction::mint_to( &spl_token::id(), @@ -77,7 +67,7 @@ pub fn process_upgrade<'a, 'info>( beneficiary_info.clone(), treasury_info.clone(), ], - &[&[TREASURY, &[treasury_bump]]], + &[&[TREASURY, &[TREASURY_BUMP]]], )?; Ok(())