From 3934f81b318a741b7edccd8bd273d6b7c349ea3e Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Fri, 16 Feb 2024 17:51:00 +0000 Subject: [PATCH] bus checks --- src/processor/initialize.rs | 38 ++++++++++++++++++++----------------- src/processor/mine.rs | 4 ++-- src/processor/reset.rs | 20 ++++++------------- src/state/bus.rs | 2 +- src/state/treasury.rs | 6 +++--- src/utils.rs | 16 ++++++++-------- tests/test_initialize.rs | 3 +-- tests/test_mine.rs | 2 +- tests/test_reset.rs | 4 ++-- 9 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 5c5f7dc..f9168ee 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -17,8 +17,8 @@ use crate::{ utils::create_pda, utils::AccountDeserialize, utils::Discriminator, - BUS, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, MINT, MINT_ADDRESS, TOKEN_DECIMALS, - TREASURY, TREASURY_ADDRESS, + BUS, BUS_ADDRESSES, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, MINT, MINT_ADDRESS, + TOKEN_DECIMALS, TREASURY, TREASURY_ADDRESS, }; pub fn process_initialize<'a, 'info>( @@ -34,29 +34,30 @@ pub fn process_initialize<'a, 'info>( return Err(ProgramError::NotEnoughAccountKeys); }; load_signer(signer)?; - // TODO Verify bus keys - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; - load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; load_uninitialized_pda(bus_0_info, &[BUS, &[0], &[args.bus_0_bump]])?; + load_uninitialized_pda(bus_1_info, &[BUS, &[1], &[args.bus_1_bump]])?; + load_uninitialized_pda(bus_2_info, &[BUS, &[2], &[args.bus_2_bump]])?; + load_uninitialized_pda(bus_3_info, &[BUS, &[3], &[args.bus_3_bump]])?; + load_uninitialized_pda(bus_4_info, &[BUS, &[4], &[args.bus_4_bump]])?; + load_uninitialized_pda(bus_5_info, &[BUS, &[5], &[args.bus_5_bump]])?; + load_uninitialized_pda(bus_6_info, &[BUS, &[6], &[args.bus_6_bump]])?; + load_uninitialized_pda(bus_7_info, &[BUS, &[7], &[args.bus_7_bump]])?; load_uninitialized_pda(mint_info, &[MINT, &[args.mint_bump]])?; - if !mint_info.key.eq(&MINT_ADDRESS) { - return Err(ProgramError::InvalidAccountData); - } load_uninitialized_pda(treasury_info, &[TREASURY, &[args.treasury_bump]])?; - if !treasury_info.key.eq(&TREASURY_ADDRESS) { - return Err(ProgramError::InvalidSeeds); - } load_uninitialized_account(treasury_tokens_info)?; load_program(system_program, system_program::id())?; load_program(token_program, spl_token::id())?; load_program(associated_token_program, spl_associated_token_account::id())?; load_sysvar(rent_sysvar, sysvar::rent::id())?; + // Verify keys + if mint_info.key.ne(&MINT_ADDRESS) { + return Err(ProgramError::InvalidSeeds); + } + if treasury_info.key.ne(&TREASURY_ADDRESS) { + return Err(ProgramError::InvalidSeeds); + } + // Initialize bus accounts let bus_infos = [ bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, @@ -73,6 +74,9 @@ pub fn process_initialize<'a, 'info>( args.bus_7_bump, ]; for i in 0..BUS_COUNT { + if bus_infos[i].key.ne(&BUS_ADDRESSES[i]) { + return Err(ProgramError::InvalidSeeds); + } create_pda( bus_infos[i], &crate::id(), @@ -85,7 +89,7 @@ pub fn process_initialize<'a, 'info>( bus_data[0] = Bus::discriminator() as u8; let mut bus = Bus::try_from_bytes_mut(&mut bus_data)?; bus.id = i as u64; - bus.available_rewards = 0; + bus.rewards = 0; } // Initialize treasury diff --git a/src/processor/mine.rs b/src/processor/mine.rs index 123d5f6..bbbb13b 100644 --- a/src/processor/mine.rs +++ b/src/processor/mine.rs @@ -63,10 +63,10 @@ pub fn process_mine<'a, 'info>( // Update claimable rewards let mut bus_data = bus_info.data.borrow_mut(); let mut bus = Bus::try_from_bytes_mut(&mut bus_data)?; - if bus.available_rewards.lt(&treasury.reward_rate) { + if bus.rewards.lt(&treasury.reward_rate) { return Err(OreError::InsufficientBusRewards.into()); } - bus.available_rewards = bus.available_rewards.saturating_sub(treasury.reward_rate); + bus.rewards = bus.rewards.saturating_sub(treasury.reward_rate); proof.claimable_rewards = proof.claimable_rewards.saturating_add(treasury.reward_rate); // Hash most recent slot hash into the next challenge to prevent pre-mining attacks diff --git a/src/processor/reset.rs b/src/processor/reset.rs index 4ab375e..c5072b5 100644 --- a/src/processor/reset.rs +++ b/src/processor/reset.rs @@ -1,6 +1,5 @@ -use bytemuck::{Pod, Zeroable}; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, program::set_return_data, + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, }; @@ -55,16 +54,16 @@ pub fn process_reset<'a, 'info>( } // Reset busses - let mut total_available_rewards = 0u64; + let mut total_bus_rewards = 0u64; for i in 0..BUS_COUNT { let mut bus_data = busses[i].data.borrow_mut(); let mut bus = Bus::try_from_bytes_mut(&mut bus_data)?; - total_available_rewards = total_available_rewards.saturating_add(bus.available_rewards); - bus.available_rewards = BUS_EPOCH_REWARDS; + total_bus_rewards = total_bus_rewards.saturating_add(bus.rewards); + bus.rewards = BUS_EPOCH_REWARDS; } // Update the reward rate for the next epoch - let total_epoch_rewards = MAX_EPOCH_REWARDS.saturating_sub(total_available_rewards); + let total_epoch_rewards = MAX_EPOCH_REWARDS.saturating_sub(total_bus_rewards); treasury.reward_rate = calculate_new_reward_rate(treasury.reward_rate, total_epoch_rewards); treasury.epoch_start_at = clock.unix_timestamp; @@ -103,7 +102,7 @@ pub(crate) fn calculate_new_reward_rate(current_rate: u64, epoch_rewards: u64) - .saturating_mul(TARGET_EPOCH_REWARDS as u128) .saturating_div(epoch_rewards as u128) as u64; - // Smooth reward rate to not change by more than a constant factor from one epoch to the next. + // Smooth reward rate so it cannot change by more than a constant factor from one epoch to the next. let new_rate_min = current_rate.saturating_div(SMOOTHING_FACTOR); let new_rate_max = current_rate.saturating_mul(SMOOTHING_FACTOR); let new_rate_smoothed = new_rate_min.max(new_rate_max.min(new_rate)); @@ -112,13 +111,6 @@ pub(crate) fn calculate_new_reward_rate(current_rate: u64, epoch_rewards: u64) - new_rate_smoothed.max(1).min(BUS_EPOCH_REWARDS) } -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] -pub struct ResetResponse { - pub new_reward_rate: u64, - pub new_supply: u64, -} - #[cfg(test)] mod tests { use crate::{calculate_new_reward_rate, SMOOTHING_FACTOR, TARGET_EPOCH_REWARDS}; diff --git a/src/state/bus.rs b/src/state/bus.rs index a94a371..4f826a7 100644 --- a/src/state/bus.rs +++ b/src/state/bus.rs @@ -12,7 +12,7 @@ pub struct Bus { pub id: u64, /// The quantity of rewards this bus can issue in the current epoch epoch. - pub available_rewards: u64, + pub rewards: u64, } impl Discriminator for Bus { diff --git a/src/state/treasury.rs b/src/state/treasury.rs index 639d653..c42d28c 100644 --- a/src/state/treasury.rs +++ b/src/state/treasury.rs @@ -10,12 +10,12 @@ use crate::{ #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] pub struct Treasury { - /// The bump of the treasury account PDA. - pub bump: u64, - /// The admin authority with permission to update the difficulty. pub admin: Pubkey, + /// The bump of the treasury account PDA. + pub bump: u64, + /// The hash difficulty. pub difficulty: Hash, diff --git a/src/utils.rs b/src/utils.rs index 8f3967c..1fb0300 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,15 +36,20 @@ pub(crate) fn create_pda<'a, 'info>( #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)] pub enum AccountDiscriminator { - Bus = 100, - Proof = 101, - Treasury = 102, + Bus = 0, + Proof = 1, + Treasury = 2, } pub trait Discriminator { fn discriminator() -> AccountDiscriminator; } +pub trait AccountDeserialize { + fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>; + fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError>; +} + #[macro_export] macro_rules! impl_to_bytes { ($struct_name:ident) => { @@ -56,11 +61,6 @@ macro_rules! impl_to_bytes { }; } -pub trait AccountDeserialize { - fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>; - fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError>; -} - #[macro_export] macro_rules! impl_account_from_bytes { ($struct_name:ident) => { diff --git a/tests/test_initialize.rs b/tests/test_initialize.rs index 7edebee..9fc6762 100644 --- a/tests/test_initialize.rs +++ b/tests/test_initialize.rs @@ -91,9 +91,8 @@ async fn test_initialize() { let bus_account = banks.get_account(bus_pdas[i].0).await.unwrap().unwrap(); assert_eq!(bus_account.owner, ore::id()); let bus = Bus::try_from_bytes(&bus_account.data).unwrap(); - // assert_eq!(bus.bump as u8, bus_pdas[i].1); assert_eq!(bus.id as u8, i as u8); - assert_eq!(bus.available_rewards, 0); + assert_eq!(bus.rewards, 0); println!( "Bus {:?} {:?} {:?}", bus_pdas[i].0, diff --git a/tests/test_mine.rs b/tests/test_mine.rs index 55b81f4..fb45236 100644 --- a/tests/test_mine.rs +++ b/tests/test_mine.rs @@ -97,7 +97,7 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, solana_program::hash &(Bus::discriminator() as u64).to_le_bytes(), Bus { id: i as u64, - available_rewards: 250_000_000, + rewards: 250_000_000, } .to_bytes(), ] diff --git a/tests/test_reset.rs b/tests/test_reset.rs index 5b3d2c9..6b938a2 100644 --- a/tests/test_reset.rs +++ b/tests/test_reset.rs @@ -56,7 +56,7 @@ async fn test_reset() { bs64::encode(&bus_account.data) ); assert_eq!(bus.id as u8, i as u8); - assert_eq!(bus.available_rewards, BUS_EPOCH_REWARDS); + assert_eq!(bus.rewards, BUS_EPOCH_REWARDS); } // Test treasury state @@ -136,7 +136,7 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { &(Bus::discriminator() as u64).to_le_bytes(), Bus { id: i as u64, - available_rewards: 0, + rewards: 0, } .to_bytes(), ]