From 0836c40f89ba70d7807a1b6ef6747c03cbb0e0d6 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Sun, 24 Mar 2024 19:21:59 +0000 Subject: [PATCH] tests and remove unneeded conditionals --- src/processor/initialize.rs | 17 +--- tests/test_initialize.rs | 152 +++++++++++++++++++++++++++++++- tests/test_mine.rs | 151 ++++++++++++++++++++++++++++--- tests/test_register.rs | 12 +++ tests/test_reset.rs | 52 +++++++++-- tests/test_update_admin.rs | 58 +++++++++--- tests/test_update_difficulty.rs | 58 ++++++++++-- 7 files changed, 445 insertions(+), 55 deletions(-) diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 0fe683f..cd29e63 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -17,9 +17,8 @@ use crate::{ utils::create_pda, utils::AccountDeserialize, utils::Discriminator, - BUS, BUS_ADDRESSES, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA, - METADATA_ADDRESS, METADATA_NAME, METADATA_SYMBOL, METADATA_URI, MINT, MINT_ADDRESS, MINT_NOISE, - TOKEN_DECIMALS, TREASURY, TREASURY_ADDRESS, + BUS, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA, METADATA_NAME, + METADATA_SYMBOL, METADATA_URI, MINT, MINT_ADDRESS, MINT_NOISE, TOKEN_DECIMALS, TREASURY, }; /// Initialize sets up the Ore program. Its responsibilities include: @@ -103,9 +102,6 @@ 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(), @@ -122,9 +118,6 @@ pub fn process_initialize<'a, 'info>( } // Initialize treasury - if treasury_info.key.ne(&TREASURY_ADDRESS) { - return Err(ProgramError::InvalidSeeds); - } create_pda( treasury_info, &crate::id(), @@ -145,9 +138,6 @@ pub fn process_initialize<'a, 'info>( drop(treasury_data); // Initialize mint - if mint_info.key.ne(&MINT_ADDRESS) { - return Err(ProgramError::InvalidSeeds); - } create_pda( mint_info, &spl_token::id(), @@ -174,9 +164,6 @@ pub fn process_initialize<'a, 'info>( )?; // Initialize mint metadata - if metadata_info.key.ne(&METADATA_ADDRESS) { - return Err(ProgramError::InvalidSeeds); - } mpl_token_metadata::instructions::CreateMetadataAccountV3Cpi { __program: metadata_program, metadata: metadata_info, diff --git a/tests/test_initialize.rs b/tests/test_initialize.rs index 8143654..e65b706 100644 --- a/tests/test_initialize.rs +++ b/tests/test_initialize.rs @@ -3,10 +3,12 @@ use mpl_token_metadata::{ types::{Key, TokenStandard}, }; use ore::{ + instruction::{InitializeArgs, OreInstruction}, state::{Bus, Treasury}, utils::AccountDeserialize, - BUS_ADDRESSES, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA_ADDRESS, - METADATA_NAME, METADATA_SYMBOL, METADATA_URI, MINT_ADDRESS, TREASURY, + BUS, BUS_ADDRESSES, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA, + METADATA_ADDRESS, METADATA_NAME, METADATA_SYMBOL, METADATA_URI, MINT, MINT_ADDRESS, MINT_NOISE, + TREASURY, }; use solana_program::{ hash::Hash, program_option::COption, program_pack::Pack, pubkey::Pubkey, rent::Rent, @@ -103,6 +105,152 @@ async fn test_initialize() { assert_eq!(treasury_tokens.close_authority, COption::None); } +#[tokio::test] +async fn test_initialize_not_enough_accounts() { + // Setup + let (mut banks, payer, blockhash) = setup_program_test_env().await; + + // Submit tx + let mut ix = ore::instruction::initialize(payer.pubkey()); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +#[tokio::test] +async fn test_initialize_bad_pda() { + // Setup + let (mut banks, payer, blockhash) = setup_program_test_env().await; + + // Pdas + let bus_pdas = [ + Pubkey::find_program_address(&[BUS, &[0]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[1]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[2]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[3]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[4]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[5]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[6]], &ore::id()), + Pubkey::find_program_address(&[BUS, &[7]], &ore::id()), + ]; + let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &ore::id()); + let treasury_pda = Pubkey::find_program_address(&[TREASURY], &ore::id()); + let metadata_pda = Pubkey::find_program_address( + &[ + METADATA, + mpl_token_metadata::ID.as_ref(), + mint_pda.0.as_ref(), + ], + &mpl_token_metadata::ID, + ); + let bad_pda = Pubkey::find_program_address(&[b"t"], &ore::id()); + + // Bad bus pda + let mut ix = ore::instruction::initialize(payer.pubkey()); + ix.accounts[1].pubkey = bad_pda.0; + ix.data = [ + OreInstruction::Initialize.to_vec(), + InitializeArgs { + bus_0_bump: bad_pda.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, + metadata_bump: metadata_pda.1, + mint_bump: mint_pda.1, + treasury_bump: treasury_pda.1, + } + .to_bytes() + .to_vec(), + ] + .concat(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); + + // Bad metadata pda + let mut ix = ore::instruction::initialize(payer.pubkey()); + ix.accounts[9].pubkey = bad_pda.0; + ix.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, + metadata_bump: bad_pda.1, + mint_bump: mint_pda.1, + treasury_bump: treasury_pda.1, + } + .to_bytes() + .to_vec(), + ] + .concat(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); + + // Bad mint pda + let mut ix = ore::instruction::initialize(payer.pubkey()); + ix.accounts[10].pubkey = bad_pda.0; + ix.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, + metadata_bump: metadata_pda.1, + mint_bump: bad_pda.1, + treasury_bump: treasury_pda.1, + } + .to_bytes() + .to_vec(), + ] + .concat(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); + + // Bad treasury pda + let mut ix = ore::instruction::initialize(payer.pubkey()); + ix.accounts[11].pubkey = bad_pda.0; + ix.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, + metadata_bump: metadata_pda.1, + mint_bump: mint_pda.1, + treasury_bump: bad_pda.1, + } + .to_bytes() + .to_vec(), + ] + .concat(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { let mut program_test = ProgramTest::new("ore", ore::ID, processor!(ore::process_instruction)); program_test.prefer_bpf(true); diff --git a/tests/test_mine.rs b/tests/test_mine.rs index 21061b4..8ae0eff 100644 --- a/tests/test_mine.rs +++ b/tests/test_mine.rs @@ -4,8 +4,8 @@ use ore::{ instruction::{MineArgs, OreInstruction}, state::{Bus, Proof, Treasury}, utils::{AccountDeserialize, Discriminator}, - BUS_ADDRESSES, BUS_COUNT, INITIAL_REWARD_RATE, MINT_ADDRESS, PROOF, START_AT, TOKEN_DECIMALS, - TREASURY, TREASURY_ADDRESS, + BUS_ADDRESSES, BUS_COUNT, EPOCH_DURATION, INITIAL_REWARD_RATE, MINT_ADDRESS, PROOF, START_AT, + TOKEN_DECIMALS, TREASURY, TREASURY_ADDRESS, }; use rand::{distributions::Uniform, Rng}; use solana_program::{ @@ -35,7 +35,7 @@ use spl_token::state::{AccountState, Mint}; #[tokio::test] async fn test_mine() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env(true).await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::Normal).await; // Submit register tx let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); @@ -135,7 +135,8 @@ async fn test_mine() { #[tokio::test] async fn test_mine_alt_proof() { // Setup - let (mut banks, payer, payer_alt, blockhash) = setup_program_test_env(true).await; + let (mut banks, payer, payer_alt, blockhash) = + setup_program_test_env(true, ClockState::Normal).await; // Submit register tx let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); @@ -193,7 +194,8 @@ async fn test_mine_alt_proof() { #[tokio::test] async fn test_mine_correct_hash_alt_proof() { // Setup - let (mut banks, payer, payer_alt, blockhash) = setup_program_test_env(true).await; + let (mut banks, payer, payer_alt, blockhash) = + setup_program_test_env(true, ClockState::Normal).await; // Submit register alt tx let proof_alt_pda = @@ -244,7 +246,7 @@ async fn test_mine_correct_hash_alt_proof() { #[tokio::test] async fn test_mine_bus_rewards_insufficient() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env(false).await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(false, ClockState::Normal).await; // Submit register tx let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); @@ -272,7 +274,7 @@ async fn test_mine_bus_rewards_insufficient() { #[tokio::test] async fn test_claim_too_large() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env(false).await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::Normal).await; // Submit register tx let ix = ore::instruction::register(payer.pubkey()); @@ -280,7 +282,7 @@ async fn test_claim_too_large() { let res = banks.process_transaction(tx).await; assert!(res.is_ok()); - // Submit mine tx + // Submit claim tx let beneficiary = get_associated_token_address(&payer.pubkey(), &ore::MINT_ADDRESS); let token_ix = create_associated_token_account( &payer.pubkey(), @@ -299,11 +301,128 @@ async fn test_claim_too_large() { assert!(res.is_err()); } +#[tokio::test] +async fn test_mine_not_enough_accounts() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::Normal).await; + + // Submit register tx + let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); + let ix = ore::instruction::register(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Find next hash + let proof_account = banks.get_account(proof_pda.0).await.unwrap().unwrap(); + let proof = Proof::try_from_bytes(&proof_account.data).unwrap(); + let (next_hash, nonce) = find_next_hash( + proof.hash.into(), + KeccakHash::new_from_array([u8::MAX; 32]), + payer.pubkey(), + ); + + // Submit mine tx + let mut ix = ore::instruction::mine(payer.pubkey(), BUS_ADDRESSES[0], next_hash.into(), nonce); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +#[tokio::test] +async fn test_mine_too_early() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::TooEarly).await; + + // Submit register tx + let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); + let ix = ore::instruction::register(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Find next hash + let proof_account = banks.get_account(proof_pda.0).await.unwrap().unwrap(); + let proof = Proof::try_from_bytes(&proof_account.data).unwrap(); + let (next_hash, nonce) = find_next_hash( + proof.hash.into(), + KeccakHash::new_from_array([u8::MAX; 32]), + payer.pubkey(), + ); + + // Submit mine tx + let ix = ore::instruction::mine(payer.pubkey(), BUS_ADDRESSES[0], next_hash.into(), nonce); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +#[tokio::test] +async fn test_mine_needs_reset() { + // Setup + let (mut banks, payer, _, blockhash) = + setup_program_test_env(true, ClockState::NeedsReset).await; + + // Submit register tx + let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); + let ix = ore::instruction::register(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Find next hash + let proof_account = banks.get_account(proof_pda.0).await.unwrap().unwrap(); + let proof = Proof::try_from_bytes(&proof_account.data).unwrap(); + let (next_hash, nonce) = find_next_hash( + proof.hash.into(), + KeccakHash::new_from_array([u8::MAX; 32]), + payer.pubkey(), + ); + + // Submit mine tx + let ix = ore::instruction::mine(payer.pubkey(), BUS_ADDRESSES[0], next_hash.into(), nonce); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +#[tokio::test] +async fn test_claim_not_enough_accounts() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::Normal).await; + + // Submit register tx + let ix = ore::instruction::register(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Submit claim tx + let beneficiary = get_associated_token_address(&payer.pubkey(), &ore::MINT_ADDRESS); + let token_ix = create_associated_token_account( + &payer.pubkey(), + &payer.pubkey(), + &ore::MINT_ADDRESS, + &spl_token::id(), + ); + let mut ix = ore::instruction::claim(payer.pubkey(), beneficiary, 0); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer( + &[token_ix, ix], + Some(&payer.pubkey()), + &[&payer], + blockhash, + ); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + #[tokio::test] async fn test_mine_fail_bad_data() { // Setup const FUZZ: usize = 10; - let (mut banks, payer, _, blockhash) = setup_program_test_env(true).await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(true, ClockState::Normal).await; // Submit register tx let proof_pda = Pubkey::find_program_address(&[PROOF, payer.pubkey().as_ref()], &ore::id()); @@ -488,8 +607,15 @@ fn find_next_hash(hash: KeccakHash, difficulty: KeccakHash, signer: Pubkey) -> ( (next_hash, nonce) } +enum ClockState { + Normal, + TooEarly, + NeedsReset, +} + async fn setup_program_test_env( funded_busses: bool, + clock_state: ClockState, ) -> (BanksClient, Keypair, Keypair, solana_program::hash::Hash) { let mut program_test = ProgramTest::new("ore", ore::ID, processor!(ore::process_instruction)); program_test.prefer_bpf(true); @@ -582,6 +708,11 @@ async fn setup_program_test_env( ); // Set sysvar + let ts = match clock_state { + ClockState::Normal => START_AT + 1, + ClockState::TooEarly => START_AT - 1, + ClockState::NeedsReset => START_AT + EPOCH_DURATION, + }; program_test.add_sysvar_account( sysvar::clock::id(), &Clock { @@ -589,7 +720,7 @@ async fn setup_program_test_env( epoch_start_timestamp: 0, epoch: 0, leader_schedule_epoch: DEFAULT_SLOTS_PER_EPOCH, - unix_timestamp: START_AT + 1, + unix_timestamp: ts, }, ); diff --git a/tests/test_register.rs b/tests/test_register.rs index e3aa4b4..454baa2 100644 --- a/tests/test_register.rs +++ b/tests/test_register.rs @@ -44,6 +44,18 @@ async fn test_register_account_with_lamports() { assert!(res.is_ok()); } +#[tokio::test] +async fn test_register_not_enough_accounts() { + let (mut banks, payer, blockhash) = setup_program_test_env().await; + + // Assert register fails + let mut ix = register(payer.pubkey()); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + #[tokio::test] async fn test_register_fail_other() { let (mut banks, payer, blockhash) = setup_program_test_env().await; diff --git a/tests/test_reset.rs b/tests/test_reset.rs index 701fbce..43fb4bd 100644 --- a/tests/test_reset.rs +++ b/tests/test_reset.rs @@ -30,7 +30,7 @@ use spl_token::state::{AccountState, Mint}; #[tokio::test] async fn test_reset() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::Normal).await; // Pdas let bus_pdas = vec![ @@ -73,7 +73,7 @@ async fn test_reset() { Pubkey::from_str("AeNqnoLwFanMd3ig9WoMxQZVwQHtCtqKMMBsT1sTrvz6").unwrap() ); assert_eq!(treasury.difficulty, INITIAL_DIFFICULTY.into()); - assert_eq!(treasury.last_reset_at, START_AT); + assert_eq!(treasury.last_reset_at, START_AT + 1); assert_eq!(treasury.reward_rate, INITIAL_REWARD_RATE.saturating_div(2)); assert_eq!(treasury.total_claimed_rewards as u8, 0); @@ -108,7 +108,7 @@ async fn test_reset() { #[tokio::test] async fn test_reset_busses_out_of_order_fail() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::Normal).await; // Pdas let signer = payer.pubkey(); @@ -153,9 +153,9 @@ async fn test_reset_busses_out_of_order_fail() { } #[tokio::test] -async fn test_reset_early() { +async fn test_reset_race() { // Setup - let (mut banks, payer, payer_alt, blockhash) = setup_program_test_env().await; + let (mut banks, payer, payer_alt, blockhash) = setup_program_test_env(ClockState::Normal).await; // Reset one passes let ix = ore::instruction::reset(payer.pubkey()); @@ -175,10 +175,35 @@ async fn test_reset_early() { assert!(res.is_err()); } +#[tokio::test] +async fn test_reset_too_early() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::TooEarly).await; + + // Reset one passes + let ix = ore::instruction::reset(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +#[tokio::test] +async fn test_reset_not_enough_keys() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::Normal).await; + + // Reset with missing account + let mut ix = ore::instruction::reset(payer.pubkey()); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + #[tokio::test] async fn test_reset_busses_duplicate_fail() { // Setup - let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::Normal).await; // Pdas let signer = payer.pubkey(); @@ -217,7 +242,7 @@ async fn test_reset_busses_duplicate_fail() { async fn test_reset_shuffle_error() { // Setup const FUZZ: u64 = 100; - let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env(ClockState::Normal).await; // Pdas let signer = payer.pubkey(); @@ -268,7 +293,12 @@ async fn test_reset_shuffle_error() { } } -async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) { +enum ClockState { + Normal, + TooEarly, +} + +async fn setup_program_test_env(clock_state: ClockState) -> (BanksClient, Keypair, Keypair, Hash) { let mut program_test = ProgramTest::new("ore", ore::ID, processor!(ore::process_instruction)); program_test.prefer_bpf(true); @@ -360,6 +390,10 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) { ); // Set sysvar + let ts = match clock_state { + ClockState::Normal => START_AT + 1, + ClockState::TooEarly => START_AT - 1, + }; program_test.add_sysvar_account( sysvar::clock::id(), &Clock { @@ -367,7 +401,7 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) { epoch_start_timestamp: 0, epoch: 0, leader_schedule_epoch: DEFAULT_SLOTS_PER_EPOCH, - unix_timestamp: START_AT, + unix_timestamp: ts, }, ); diff --git a/tests/test_update_admin.rs b/tests/test_update_admin.rs index 9353345..b3bd4a7 100644 --- a/tests/test_update_admin.rs +++ b/tests/test_update_admin.rs @@ -1,5 +1,7 @@ use ore::{state::Treasury, utils::AccountDeserialize, TREASURY_ADDRESS}; -use solana_program::{hash::Hash, pubkey::Pubkey, rent::Rent}; +use solana_program::{ + hash::Hash, native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, rent::Rent, system_program, +}; use solana_program_test::{processor, read_file, BanksClient, ProgramTest}; use solana_sdk::{ account::Account, @@ -10,7 +12,7 @@ use solana_sdk::{ #[tokio::test] async fn test_update_admin() { // Setup - let (mut banks, payer, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env().await; // Submit tx let ix = ore::instruction::initialize(payer.pubkey()); @@ -52,7 +54,7 @@ async fn test_update_admin() { #[tokio::test] async fn test_update_admin_bad_signer() { // Setup - let (mut banks, payer, blockhash) = setup_program_test_env().await; + let (mut banks, payer, alt_payer, blockhash) = setup_program_test_env().await; // Submit tx let ix = ore::instruction::initialize(payer.pubkey()); @@ -60,16 +62,38 @@ async fn test_update_admin_bad_signer() { let res = banks.process_transaction(tx).await; assert!(res.is_ok()); - // Submit update difficulty ix - let signer = Keypair::new(); - let ix = ore::instruction::update_admin(signer.pubkey(), Pubkey::new_unique()); - let tx = - Transaction::new_signed_with_payer(&[ix], Some(&signer.pubkey()), &[&signer], blockhash); + // Submit ix + let ix = ore::instruction::update_admin(alt_payer.pubkey(), Pubkey::new_unique()); + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&alt_payer.pubkey()), + &[&alt_payer], + blockhash, + ); let res = banks.process_transaction(tx).await; assert!(res.is_err()); } -async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { +#[tokio::test] +async fn test_update_admin_not_enough_accounts() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + + // Submit tx + let ix = ore::instruction::initialize(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Submit ix without enough accounts + let mut ix = ore::instruction::update_admin(payer.pubkey(), Pubkey::new_unique()); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) { let mut program_test = ProgramTest::new("ore", ore::ID, processor!(ore::process_instruction)); program_test.prefer_bpf(true); @@ -86,5 +110,19 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { }, ); - program_test.start().await + // Setup alt payer + let payer_alt = Keypair::new(); + program_test.add_account( + payer_alt.pubkey(), + Account { + lamports: LAMPORTS_PER_SOL, + data: vec![], + owner: system_program::id(), + executable: false, + rent_epoch: 0, + }, + ); + + let (banks, payer, blockhash) = program_test.start().await; + (banks, payer, payer_alt, blockhash) } diff --git a/tests/test_update_difficulty.rs b/tests/test_update_difficulty.rs index 504a86e..3c7d335 100644 --- a/tests/test_update_difficulty.rs +++ b/tests/test_update_difficulty.rs @@ -1,5 +1,8 @@ use ore::{state::Treasury, utils::AccountDeserialize, TREASURY_ADDRESS}; -use solana_program::{hash::Hash, keccak::Hash as KeccakHash, rent::Rent}; +use solana_program::{ + hash::Hash, keccak::Hash as KeccakHash, native_token::LAMPORTS_PER_SOL, rent::Rent, + system_program, +}; use solana_program_test::{processor, read_file, BanksClient, ProgramTest}; use solana_sdk::{ account::Account, @@ -10,7 +13,7 @@ use solana_sdk::{ #[tokio::test] async fn test_update_difficulty() { // Setup - let (mut banks, payer, blockhash) = setup_program_test_env().await; + let (mut banks, payer, _, blockhash) = setup_program_test_env().await; // Submit tx let ix = ore::instruction::initialize(payer.pubkey()); @@ -46,7 +49,7 @@ async fn test_update_difficulty() { #[tokio::test] async fn test_update_difficulty_bad_signer() { // Setup - let (mut banks, payer, blockhash) = setup_program_test_env().await; + let (mut banks, payer, alt_payer, blockhash) = setup_program_test_env().await; // Submit tx let ix = ore::instruction::initialize(payer.pubkey()); @@ -55,16 +58,39 @@ async fn test_update_difficulty_bad_signer() { assert!(res.is_ok()); // Submit update difficulty ix - let signer = Keypair::new(); let new_difficulty = KeccakHash::new_unique(); - let ix = ore::instruction::update_difficulty(signer.pubkey(), new_difficulty.into()); - let tx = - Transaction::new_signed_with_payer(&[ix], Some(&signer.pubkey()), &[&signer], blockhash); + let ix = ore::instruction::update_difficulty(alt_payer.pubkey(), new_difficulty.into()); + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&alt_payer.pubkey()), + &[&alt_payer], + blockhash, + ); let res = banks.process_transaction(tx).await; assert!(res.is_err()); } -async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { +#[tokio::test] +async fn test_update_difficulty_not_enough_accounts() { + // Setup + let (mut banks, payer, _, blockhash) = setup_program_test_env().await; + + // Submit tx + let ix = ore::instruction::initialize(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Submit ix without enough accounts + let new_difficulty = KeccakHash::new_unique(); + let mut ix = ore::instruction::update_difficulty(payer.pubkey(), new_difficulty.into()); + ix.accounts.remove(1); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_err()); +} + +async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) { let mut program_test = ProgramTest::new("ore", ore::ID, processor!(ore::process_instruction)); program_test.prefer_bpf(true); @@ -81,5 +107,19 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { }, ); - program_test.start().await + // Setup alt payer + let payer_alt = Keypair::new(); + program_test.add_account( + payer_alt.pubkey(), + Account { + lamports: LAMPORTS_PER_SOL, + data: vec![], + owner: system_program::id(), + executable: false, + rent_epoch: 0, + }, + ); + + let (banks, payer, blockhash) = program_test.start().await; + (banks, payer, payer_alt, blockhash) }