diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 212193104d..3f2be50198 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -634,7 +634,8 @@ mod tests { let stake_address = Pubkey::new_unique(); let stake_account = create_default_stake_account(); let rent_address = sysvar::rent::id(); - let rent_account = account::create_account_shared_data_for_test(&Rent::default()); + let rent = Rent::default(); + let rent_account = account::create_account_shared_data_for_test(&rent); let rewards_address = sysvar::rewards::id(); let rewards_account = account::create_account_shared_data_for_test(&sysvar::rewards::Rewards::new(0.0)); @@ -648,6 +649,8 @@ mod tests { account::create_account_shared_data_for_test(&sysvar::clock::Clock::default()); let config_address = stake_config::id(); let config_account = config::create_account(0, &stake_config::Config::default()); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); + let withdrawal_amount = rent_exempt_reserve + MINIMUM_STAKE_DELEGATION; // gets the "is_empty()" check process_instruction( @@ -769,7 +772,7 @@ mod tests { // Tests 3rd keyed account is of correct type (Clock instead of rewards) in withdraw process_instruction( - &serialize(&StakeInstruction::Withdraw(42)).unwrap(), + &serialize(&StakeInstruction::Withdraw(withdrawal_amount)).unwrap(), vec![ (stake_address, stake_account.clone()), (vote_address, vote_account), @@ -803,7 +806,7 @@ mod tests { // Tests correct number of accounts are provided in withdraw process_instruction( - &serialize(&StakeInstruction::Withdraw(42)).unwrap(), + &serialize(&StakeInstruction::Withdraw(withdrawal_amount)).unwrap(), vec![(stake_address, stake_account.clone())], vec![AccountMeta { pubkey: stake_address, @@ -858,6 +861,10 @@ mod tests { let clock_account = account::create_account_shared_data_for_test(&Clock::default()); let custodian = Pubkey::new_unique(); let custodian_account = create_default_account(); + let rent = Rent::default(); + let rent_address = sysvar::rent::id(); + let rent_account = account::create_account_shared_data_for_test(&rent); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); // Test InitializeChecked with non-signing withdrawer let mut instruction = @@ -870,12 +877,10 @@ mod tests { // Test InitializeChecked with withdrawer signer let stake_account = AccountSharedData::new( - 1_000_000_000, + rent_exempt_reserve + MINIMUM_STAKE_DELEGATION, std::mem::size_of::(), &id(), ); - let rent_address = sysvar::rent::id(); - let rent_account = account::create_account_shared_data_for_test(&Rent::default()); process_instruction( &serialize(&StakeInstruction::InitializeChecked).unwrap(), vec![ @@ -1192,7 +1197,9 @@ mod tests { #[test] fn test_stake_initialize() { - let stake_lamports = 42; + let rent = Rent::default(); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); + let stake_lamports = rent_exempt_reserve + MINIMUM_STAKE_DELEGATION; let stake_address = solana_sdk::pubkey::new_rand(); let stake_account = AccountSharedData::new(stake_lamports, std::mem::size_of::(), &id()); @@ -1211,7 +1218,7 @@ mod tests { (stake_address, stake_account.clone()), ( sysvar::rent::id(), - account::create_account_shared_data_for_test(&Rent::free()), + account::create_account_shared_data_for_test(&rent), ), ]; let instruction_accounts = vec![ @@ -1238,11 +1245,9 @@ mod tests { assert_eq!( from(&accounts[0]).unwrap(), StakeState::Initialized(Meta { + authorized: Authorized::auto(&stake_address), + rent_exempt_reserve, lockup, - ..Meta { - authorized: Authorized::auto(&stake_address), - ..Meta::default() - } }), ); @@ -1256,12 +1261,12 @@ mod tests { ); transaction_accounts[0] = (stake_address, stake_account); - // not enough balance for rent... + // not enough balance for rent and minimum delegation... transaction_accounts[1] = ( sysvar::rent::id(), account::create_account_shared_data_for_test(&Rent { - lamports_per_byte_year: 42, - ..Rent::free() + lamports_per_byte_year: rent.lamports_per_byte_year + 1, + ..rent }), ); process_instruction( @@ -2325,7 +2330,7 @@ mod tests { #[test] fn test_split() { let stake_address = solana_sdk::pubkey::new_rand(); - let stake_lamports = 42; + let stake_lamports = MINIMUM_STAKE_DELEGATION * 2; let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, @@ -2421,7 +2426,7 @@ mod tests { let authority_address = solana_sdk::pubkey::new_rand(); let custodian_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); - let stake_lamports = 42; + let stake_lamports = MINIMUM_STAKE_DELEGATION; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &StakeState::Uninitialized, @@ -3165,7 +3170,7 @@ mod tests { let custodian_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); - let stake_lamports = 42; + let stake_lamports = MINIMUM_STAKE_DELEGATION; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &StakeState::Uninitialized, diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 1de6cde8e3..71f6fd31ee 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -2494,8 +2494,10 @@ mod tests { #[test] fn test_split_source_uninitialized() { + let rent = Rent::default(); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); let stake_pubkey = solana_sdk::pubkey::new_rand(); - let stake_lamports = 42; + let stake_lamports = (rent_exempt_reserve + MINIMUM_STAKE_DELEGATION) * 2; let stake_account = AccountSharedData::new_ref_data_with_space( stake_lamports, &StakeState::Uninitialized, @@ -2614,12 +2616,17 @@ mod tests { #[test] fn test_split_more_than_staked() { + let rent = Rent::default(); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); let stake_pubkey = solana_sdk::pubkey::new_rand(); - let stake_lamports = 42; + let stake_lamports = (rent_exempt_reserve + MINIMUM_STAKE_DELEGATION) * 2; let stake_account = AccountSharedData::new_ref_data_with_space( stake_lamports, &StakeState::Stake( - Meta::auto(&stake_pubkey), + Meta { + rent_exempt_reserve, + ..Meta::auto(&stake_pubkey) + }, just_stake(stake_lamports / 2 - 1), ), std::mem::size_of::(), @@ -2648,10 +2655,12 @@ mod tests { #[test] fn test_split_with_rent() { + let rent = Rent::default(); + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); + let minimum_balance = rent_exempt_reserve + MINIMUM_STAKE_DELEGATION; let stake_pubkey = solana_sdk::pubkey::new_rand(); let split_stake_pubkey = solana_sdk::pubkey::new_rand(); - let stake_lamports = 10_000_000; - let rent_exempt_reserve = 2_282_880; + let stake_lamports = minimum_balance * 2; let signers = vec![stake_pubkey].into_iter().collect(); let meta = Meta { @@ -2710,10 +2719,10 @@ mod tests { split_stake_keyed_account .account .borrow_mut() - .set_lamports(10_000_000); + .set_lamports(minimum_balance); assert_eq!( stake_keyed_account.split( - stake_lamports - (rent_exempt_reserve + 1), // leave rent_exempt_reserve + 1 in original account + stake_lamports - minimum_balance, &split_stake_keyed_account, &signers ), @@ -2728,7 +2737,7 @@ mod tests { *meta, Stake { delegation: Delegation { - stake: stake_lamports - rent_exempt_reserve - 1, + stake: stake_lamports - minimum_balance, ..stake.delegation }, ..*stake @@ -2737,11 +2746,11 @@ mod tests { ); assert_eq!( stake_keyed_account.account.borrow().lamports(), - rent_exempt_reserve + 1 + minimum_balance, ); assert_eq!( split_stake_keyed_account.account.borrow().lamports(), - 10_000_000 + stake_lamports - rent_exempt_reserve - 1 + stake_lamports, ); } } @@ -2752,7 +2761,7 @@ mod tests { let stake_pubkey = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); - let stake_lamports = rent_exempt_reserve * 3; // Enough to allow half to be split and remain rent-exempt + let stake_lamports = (rent_exempt_reserve + MINIMUM_STAKE_DELEGATION) * 2; let split_stake_pubkey = solana_sdk::pubkey::new_rand(); let signers = vec![stake_pubkey].into_iter().collect(); @@ -2767,7 +2776,13 @@ mod tests { // Test various account prefunding, including empty, less than rent_exempt_reserve, exactly // rent_exempt_reserve, and more than rent_exempt_reserve. The empty case is not covered in // test_split, since that test uses a Meta with rent_exempt_reserve = 0 - let split_lamport_balances = vec![0, 1, rent_exempt_reserve, rent_exempt_reserve + 1]; + let split_lamport_balances = vec![ + 0, + rent_exempt_reserve - 1, + rent_exempt_reserve, + rent_exempt_reserve + MINIMUM_STAKE_DELEGATION - 1, + rent_exempt_reserve + MINIMUM_STAKE_DELEGATION, + ]; for initial_balance in split_lamport_balances { let split_stake_account = AccountSharedData::new_ref_data_with_space( initial_balance, @@ -2852,7 +2867,7 @@ mod tests { let stake_pubkey = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); - let stake_lamports = rent_exempt_reserve * 3; // Enough to allow half to be split and remain rent-exempt + let stake_lamports = (rent_exempt_reserve + MINIMUM_STAKE_DELEGATION) * 2; let split_stake_pubkey = solana_sdk::pubkey::new_rand(); let signers = vec![stake_pubkey].into_iter().collect(); @@ -2876,9 +2891,10 @@ mod tests { // test_split, since that test uses a Meta with rent_exempt_reserve = 0 let split_lamport_balances = vec![ 0, - 1, + expected_rent_exempt_reserve - 1, expected_rent_exempt_reserve, - expected_rent_exempt_reserve + 1, + expected_rent_exempt_reserve + MINIMUM_STAKE_DELEGATION - 1, + expected_rent_exempt_reserve + MINIMUM_STAKE_DELEGATION, ]; for initial_balance in split_lamport_balances { let split_stake_account = AccountSharedData::new_ref_data_with_space( @@ -3033,7 +3049,7 @@ mod tests { let stake_pubkey = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); - let stake_lamports = rent_exempt_reserve * 3; // Arbitrary amount over rent_exempt_reserve + let stake_lamports = rent_exempt_reserve + MINIMUM_STAKE_DELEGATION; let split_stake_pubkey = solana_sdk::pubkey::new_rand(); let signers = vec![stake_pubkey].into_iter().collect(); @@ -3119,7 +3135,7 @@ mod tests { let stake_pubkey = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); - let stake_lamports = rent_exempt_reserve * 3; // Arbitrary amount over rent_exempt_reserve + let stake_lamports = rent_exempt_reserve + MINIMUM_STAKE_DELEGATION; let split_stake_pubkey = solana_sdk::pubkey::new_rand(); let signers = vec![stake_pubkey].into_iter().collect(); @@ -3134,7 +3150,13 @@ mod tests { // Test various account prefunding, including empty, less than rent_exempt_reserve, exactly // rent_exempt_reserve, and more than rent_exempt_reserve. Technically, the empty case is // covered in test_split_100_percent_of_source, but included here as well for readability - let split_lamport_balances = vec![0, 1, rent_exempt_reserve, rent_exempt_reserve + 1]; + let split_lamport_balances = vec![ + 0, + rent_exempt_reserve - 1, + rent_exempt_reserve, + rent_exempt_reserve + MINIMUM_STAKE_DELEGATION - 1, + rent_exempt_reserve + MINIMUM_STAKE_DELEGATION, + ]; for initial_balance in split_lamport_balances { let split_stake_account = AccountSharedData::new_ref_data_with_space( initial_balance,