Skip to content

Commit f9b3fa7

Browse files
committed
test inactive
1 parent ad02f8a commit f9b3fa7

3 files changed

Lines changed: 103 additions & 35 deletions

File tree

program/tests/helpers/stake.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,26 @@
44
use {
55
crate::get_account,
66
bincode::deserialize,
7+
solana_account::AccountSharedData,
78
solana_hash::Hash,
89
solana_keypair::Keypair,
910
solana_native_token::LAMPORTS_PER_SOL,
1011
solana_program_test::BanksClient,
12+
solana_program_test::ProgramTestContext,
1113
solana_pubkey::Pubkey,
1214
solana_signer::Signer,
1315
solana_stake_interface::{
1416
instruction as stake_instruction, program as stake_program,
15-
state::{Authorized, Lockup, Meta, Stake, StakeStateV2},
17+
stake_flags::StakeFlags,
18+
state::{Authorized, Delegation, Lockup, Meta, Stake, StakeStateV2},
1619
},
1720
solana_system_interface::instruction as system_instruction,
1821
solana_transaction::Transaction,
1922
std::convert::TryInto,
2023
};
2124

2225
pub const TEST_STAKE_AMOUNT: u64 = 10_000_000_000; // 10 sol
26+
pub const MANGLED_DELEGATION: u64 = 12345;
2327

2428
pub async fn get_stake_account(
2529
banks_client: &mut BanksClient,
@@ -145,3 +149,31 @@ pub async fn delegate_stake_account(
145149
transaction.sign(&[payer, authorized], *recent_blockhash);
146150
banks_client.process_transaction(transaction).await.unwrap();
147151
}
152+
153+
pub async fn force_deactivate_stake_account(context: &mut ProgramTestContext, pubkey: &Pubkey) {
154+
let (meta, stake, _) = get_stake_account(&mut context.banks_client, pubkey).await;
155+
let delegation = Delegation {
156+
activation_epoch: 0,
157+
deactivation_epoch: 0,
158+
// break anything which erroneously uses this in calculations without redelegating
159+
stake: MANGLED_DELEGATION,
160+
..stake.unwrap().delegation
161+
};
162+
let mut account_data = vec![0; std::mem::size_of::<StakeStateV2>()];
163+
bincode::serialize_into(
164+
&mut account_data[..],
165+
&StakeStateV2::Stake(
166+
meta,
167+
Stake {
168+
delegation,
169+
..stake.unwrap()
170+
},
171+
StakeFlags::empty(),
172+
),
173+
)
174+
.unwrap();
175+
176+
let mut stake_account = get_account(&mut context.banks_client, pubkey).await;
177+
stake_account.data = account_data;
178+
context.set_account(pubkey, &AccountSharedData::from(stake_account));
179+
}

program/tests/replenish.rs

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@ mod helpers;
44

55
use {
66
helpers::*,
7-
solana_account::AccountSharedData,
87
solana_clock::Clock,
98
solana_program_test::*,
109
solana_signer::Signer,
1110
solana_stake_interface::{
12-
instruction as stake_instruction,
13-
stake_flags::StakeFlags,
14-
stake_history::StakeHistory,
15-
state::{Delegation, Stake, StakeStateV2},
11+
instruction as stake_instruction, stake_history::StakeHistory, state::StakeStateV2,
1612
},
1713
solana_transaction::Transaction,
1814
spl_single_pool::{error::SinglePoolError, id, instruction},
@@ -58,36 +54,9 @@ async fn reactivate_success(
5854

5955
advance_epoch(&mut context).await;
6056

61-
// deactivate the pool stake account
6257
if reactivate_pool {
63-
let (meta, stake, _) =
64-
get_stake_account(&mut context.banks_client, &accounts.stake_account).await;
65-
let delegation = Delegation {
66-
activation_epoch: 0,
67-
deactivation_epoch: 0,
68-
..stake.unwrap().delegation
69-
};
70-
let mut account_data = vec![0; std::mem::size_of::<StakeStateV2>()];
71-
bincode::serialize_into(
72-
&mut account_data[..],
73-
&StakeStateV2::Stake(
74-
meta,
75-
Stake {
76-
delegation,
77-
..stake.unwrap()
78-
},
79-
StakeFlags::empty(),
80-
),
81-
)
82-
.unwrap();
83-
84-
let mut stake_account =
85-
get_account(&mut context.banks_client, &accounts.stake_account).await;
86-
stake_account.data = account_data;
87-
context.set_account(
88-
&accounts.stake_account,
89-
&AccountSharedData::from(stake_account),
90-
);
58+
// deactivate the pool stake account
59+
force_deactivate_stake_account(&mut context, &accounts.stake_account).await;
9160

9261
// active deposit into deactivated pool fails
9362
let instructions = instruction::deposit(

program/tests/withdraw.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,70 @@ async fn fail_withdraw_to_onramp() {
291291
.unwrap_err();
292292
check_error(e, SinglePoolError::InvalidPoolStakeAccountUsage);
293293
}
294+
295+
#[test_matrix(
296+
[StakeProgramVersion::Stable, StakeProgramVersion::Beta, StakeProgramVersion::Edge]
297+
)]
298+
#[tokio::test]
299+
async fn success_withdraw_from_inactive(stake_version: StakeProgramVersion) {
300+
// this test would fail on bpf stake v1-4 because of a bug in Split
301+
// when this assert fails, it means v5 is stable. delete this entire block
302+
if stake_version == StakeProgramVersion::Stable {
303+
assert!(stake_version
304+
.basename()
305+
.unwrap()
306+
.starts_with("solana_stake_program-v4"));
307+
308+
return;
309+
}
310+
311+
let Some(program_test) = program_test(stake_version) else {
312+
return;
313+
};
314+
let mut context = program_test.start_with_context().await;
315+
316+
let accounts = SinglePoolAccounts::default();
317+
accounts
318+
.initialize_for_withdraw(&mut context, TEST_STAKE_AMOUNT, None, true)
319+
.await;
320+
321+
force_deactivate_stake_account(&mut context, &accounts.stake_account).await;
322+
323+
let (_, pool_stake_before, _) =
324+
get_stake_account(&mut context.banks_client, &accounts.stake_account).await;
325+
326+
// this proves we arent using delegation for math
327+
assert_eq!(
328+
pool_stake_before.unwrap().delegation.stake,
329+
MANGLED_DELEGATION
330+
);
331+
332+
let instructions = instruction::withdraw(
333+
&id(),
334+
&accounts.pool,
335+
&accounts.alice_stake.pubkey(),
336+
&accounts.alice.pubkey(),
337+
&accounts.alice_token,
338+
&accounts.alice.pubkey(),
339+
get_token_balance(&mut context.banks_client, &accounts.alice_token).await,
340+
);
341+
let transaction = Transaction::new_signed_with_payer(
342+
&instructions,
343+
Some(&accounts.alice.pubkey()),
344+
&[&accounts.alice],
345+
context.last_blockhash,
346+
);
347+
348+
context
349+
.banks_client
350+
.process_transaction(transaction)
351+
.await
352+
.unwrap();
353+
354+
let (_, _, alice_lamports_after) =
355+
get_stake_account(&mut context.banks_client, &accounts.alice_stake.pubkey()).await;
356+
assert_eq!(
357+
alice_lamports_after,
358+
TEST_STAKE_AMOUNT + get_stake_account_rent(&mut context.banks_client).await
359+
);
360+
}

0 commit comments

Comments
 (0)