diff --git a/controller/program/tests/tests/admin/add_lst.rs b/controller/program/tests/tests/admin/add_lst.rs index 8143b219..c706128e 100644 --- a/controller/program/tests/tests/admin/add_lst.rs +++ b/controller/program/tests/tests/admin/add_lst.rs @@ -335,25 +335,31 @@ fn add_lst_proptest( Ok(()) } +fn add_lst_correct_strat( +) -> impl Strategy { + (any_normal_pk(), any_normal_pk()).prop_flat_map(|(payer, mint)| { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }) + .prop_filter("admin cannot be system program", |pool| { + pool.admin != SYS_PROG_ID + }), + any_lst_state_list(Default::default(), None, 0..=0) + .prop_filter("mint must not be in list", move |lsl| { + !lsl.all_pool_reserves.contains_key(&mint) + }), + Just(payer), + Just(mint), + ) + }) +} + proptest! { #[test] fn add_lst_any( - (pool, lsl, payer, mint) in - (any_normal_pk(), any_normal_pk()) - .prop_flat_map(|(payer, mint)| { - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }).prop_filter("admin cannot be system program", |pool| pool.admin != SYS_PROG_ID), - any_lst_state_list(Default::default(), None, 0..=0) - .prop_filter("mint must not be in list", move |lsl| { - !lsl.all_pool_reserves.contains_key(&mint) - }), - Just(payer), - Just(mint), - ) - }), + (pool, lsl, payer, mint) in add_lst_correct_strat(), ) { add_lst_proptest( pool, @@ -371,26 +377,34 @@ proptest! { } } +fn add_lst_unauthorized_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_normal_pk(), + any_normal_pk(), + ) + .prop_flat_map(|(pool, payer, mint)| { + ( + Just(pool), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) + .prop_filter("mint must not be in list", move |lsl| { + !lsl.all_pool_reserves.contains_key(&mint) + }), + Just(payer), + any_normal_pk().prop_filter("cannot be eq admin", move |x| *x != pool.admin), + Just(mint), + ) + }) +} + proptest! { #[test] fn add_lst_unauthorized_any( - (pool, lsl, payer, non_admin, mint) in - (any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), any_normal_pk(), any_normal_pk()) - .prop_flat_map(|(pool, payer, mint)| { - ( - Just(pool), - any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) - .prop_filter("mint must not be in list", move |lsl| { - !lsl.all_pool_reserves.contains_key(&mint) - }), - Just(payer), - any_normal_pk().prop_filter("cannot be eq admin", move |x| *x != pool.admin), - Just(mint), - ) - }), + (pool, lsl, payer, non_admin, mint) in add_lst_unauthorized_strat(), ) { add_lst_proptest( pool, @@ -408,28 +422,40 @@ proptest! { } } +fn add_lst_rebalancing_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() + .with_is_disabled(false) + .with_is_rebalancing(true) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), + ..Default::default() + }), + any_normal_pk(), + any_normal_pk(), + ) + .prop_flat_map(|(pool, payer, mint)| { + ( + Just(pool), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) + .prop_filter("mint must not be in list", move |lsl| { + !lsl.all_pool_reserves.contains_key(&mint) + }), + Just(payer), + Just(mint), + ) + }) +} + proptest! { #[test] fn add_lst_rebalancing_any( - (pool, lsl, payer, mint) in - (any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() - .with_is_disabled(false) - .with_is_rebalancing(true) - .build().0.map(|x| Some(Just(x).boxed()))), - ..Default::default() - }), any_normal_pk(), any_normal_pk()) - .prop_flat_map(|(pool, payer, mint)| { - ( - Just(pool), - any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) - .prop_filter("mint must not be in list", move |lsl| { - !lsl.all_pool_reserves.contains_key(&mint) - }), - Just(payer), - Just(mint), - ) - }), + (pool, lsl, payer, mint) in add_lst_rebalancing_strat(), ) { add_lst_proptest( pool, @@ -447,28 +473,40 @@ proptest! { } } +fn add_lst_disabled_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() + .with_is_disabled(true) + .with_is_rebalancing(false) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), + ..Default::default() + }), + any_normal_pk(), + any_normal_pk(), + ) + .prop_flat_map(|(pool, payer, mint)| { + ( + Just(pool), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) + .prop_filter("mint must not be in list", move |lsl| { + !lsl.all_pool_reserves.contains_key(&mint) + }), + Just(payer), + Just(mint), + ) + }) +} + proptest! { #[test] fn add_lst_disabled_any( - (pool, lsl, payer, mint) in - (any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() - .with_is_disabled(true) - .with_is_rebalancing(false) - .build().0.map(|x| Some(Just(x).boxed()))), - ..Default::default() - }), any_normal_pk(), any_normal_pk()) - .prop_flat_map(|(pool, payer, mint)| { - ( - Just(pool), - any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES) - .prop_filter("mint must not be in list", move |lsl| { - !lsl.all_pool_reserves.contains_key(&mint) - }), - Just(payer), - Just(mint), - ) - }), + (pool, lsl, payer, mint) in add_lst_disabled_strat(), ) { add_lst_proptest( pool, @@ -486,26 +524,25 @@ proptest! { } } +fn add_lst_duplicate_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_lst_state_list(Default::default(), None, 1..=MAX_LST_STATES), + ) + .prop_flat_map(|(pool, lsl)| { + let existing_mint = *lsl.all_pool_reserves.keys().next().unwrap(); + (Just(pool), Just(lsl), any_normal_pk(), Just(existing_mint)) + }) +} + proptest! { #[test] fn add_lst_duplicate_any( - (pool, lsl, payer, existing_mint) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_lst_state_list(Default::default(), None, 1..=MAX_LST_STATES) - ) - .prop_flat_map(|(pool, lsl)| { - let existing_mint = *lsl.all_pool_reserves.keys().next().unwrap(); - ( - Just(pool), - Just(lsl), - any_normal_pk(), - Just(existing_mint), - ) - }), + (pool, lsl, payer, existing_mint) in add_lst_duplicate_strat(), ) { add_lst_proptest( pool, @@ -523,14 +560,17 @@ proptest! { } } -proptest! { - #[test] - fn add_lst_non_exec_svc_any( - (pool, lsl, payer, mint, sol_value_calculator) in - (any_pool_state(AnyPoolStateArgs { +fn add_lst_non_exec_svc_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { bools: PoolStateBools::normal(), ..Default::default() - }), any_normal_pk(), any_normal_pk(), any_normal_pk()) + }), + any_normal_pk(), + any_normal_pk(), + any_normal_pk(), + ) .prop_flat_map(|(pool, payer, mint, sol_value_calculator)| { ( Just(pool), @@ -542,7 +582,13 @@ proptest! { Just(mint), Just(sol_value_calculator), ) - }), + }) +} + +proptest! { + #[test] + fn add_lst_non_exec_svc_any( + (pool, lsl, payer, mint, sol_value_calculator) in add_lst_non_exec_svc_strat(), ) { add_lst_proptest( pool, diff --git a/controller/program/tests/tests/admin/remove_lst.rs b/controller/program/tests/tests/admin/remove_lst.rs index bf65edaa..c8cfcf4f 100644 --- a/controller/program/tests/tests/admin/remove_lst.rs +++ b/controller/program/tests/tests/admin/remove_lst.rs @@ -377,32 +377,37 @@ fn remove_lst_proptest( Ok(()) } +fn remove_lst_correct_strat() -> impl Strategy +{ + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some(Just(0).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), + any_normal_pk(), + ) + }) +} + proptest! { #[test] fn remove_lst_any( - (pool, lsl, lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some(Just(0).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) - ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), - any_normal_pk(), - ) - }) + (pool, lsl, lst_idx, refund_rent_to) in remove_lst_correct_strat(), ) { remove_lst_proptest( pool, @@ -416,33 +421,38 @@ proptest! { } } +fn remove_lst_unauthorized_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some(Just(0).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + any_normal_pk().prop_filter("cannot be eq admin", move |x| *x != pool.admin), + (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), + any_normal_pk(), + ) + }) +} + proptest! { #[test] fn remove_lst_unauthorized_any( - (pool, lsl, non_admin, lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some(Just(0).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) - ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - any_normal_pk().prop_filter("cannot be eq admin", move |x| *x != pool.admin), - (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), - any_normal_pk(), - ) - }) + (pool, lsl, non_admin, lst_idx, refund_rent_to) in remove_lst_unauthorized_strat(), ) { remove_lst_proptest( pool, @@ -456,35 +466,44 @@ proptest! { } } -proptest! { - #[test] - fn remove_lst_rebalancing_any( - (pool, lsl, lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() +fn remove_lst_rebalancing_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() .with_is_disabled(false) .with_is_rebalancing(true) - .build().0.map(|x| Some(Just(x).boxed()))), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some(Just(0).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some(Just(0).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), + any_normal_pk(), ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), - any_normal_pk(), - ) - }) + }) +} + +proptest! { + #[test] + fn remove_lst_rebalancing_any( + (pool, lsl, lst_idx, refund_rent_to) in remove_lst_rebalancing_strat(), ) { remove_lst_proptest( pool, @@ -498,35 +517,44 @@ proptest! { } } -proptest! { - #[test] - fn remove_lst_disabled_any( - (pool, lsl, lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() +fn remove_lst_disabled_strat() -> impl Strategy +{ + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() .with_is_disabled(true) .with_is_rebalancing(false) - .build().0.map(|x| Some(Just(x).boxed()))), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some(Just(0).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some(Just(0).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), + any_normal_pk(), ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), - any_normal_pk(), - ) - }) + }) +} + +proptest! { + #[test] + fn remove_lst_disabled_any( + (pool, lsl, lst_idx, refund_rent_to) in remove_lst_disabled_strat(), ) { remove_lst_proptest( pool, @@ -540,32 +568,37 @@ proptest! { } } +fn remove_lst_still_has_value_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some((1..u64::MAX).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), + any_normal_pk(), + ) + }) +} + proptest! { #[test] fn remove_lst_still_has_value_any( - (pool, lsl, lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some((1..u64::MAX).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) - ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - (0..lsl_clone.protocol_fee_accumulators.len() as u32).boxed(), - any_normal_pk(), - ) - }) + (pool, lsl, lst_idx, refund_rent_to) in remove_lst_still_has_value_strat(), ) { remove_lst_proptest( pool, @@ -579,32 +612,37 @@ proptest! { } } +fn remove_lst_invalid_lst_idx_strat( +) -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_lst_state_list( + AnyLstStateArgs { + sol_value: Some(Just(0).boxed()), + ..Default::default() + }, + None, + 1..=MAX_LST_STATES, + ), + ) + .prop_flat_map(|(pool, lsl)| { + let lsl_clone = lsl.clone(); + ( + Just(pool), + Just(lsl), + (lsl_clone.protocol_fee_accumulators.len() as u32..u32::MAX).boxed(), + any_normal_pk(), + ) + }) +} + proptest! { #[test] fn remove_lst_invalid_lst_idx_any( - (pool, lsl, invalid_lst_idx, refund_rent_to) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_lst_state_list( - AnyLstStateArgs { - sol_value: Some(Just(0).boxed()), - ..Default::default() - }, - None, 1..=MAX_LST_STATES - ) - ) - .prop_flat_map(|(pool, lsl)| { - let lsl_clone = lsl.clone(); - ( - Just(pool), - Just(lsl), - (lsl_clone.protocol_fee_accumulators.len() as u32..u32::MAX).boxed(), - any_normal_pk(), - ) - }) + (pool, lsl, invalid_lst_idx, refund_rent_to) in remove_lst_invalid_lst_idx_strat(), ) { remove_lst_proptest( pool, diff --git a/controller/program/tests/tests/admin/set_sol_value_calculator.rs b/controller/program/tests/tests/admin/set_sol_value_calculator.rs index fb6bf6e9..27e96766 100644 --- a/controller/program/tests/tests/admin/set_sol_value_calculator.rs +++ b/controller/program/tests/tests/admin/set_sol_value_calculator.rs @@ -15,9 +15,12 @@ use inf1_ctl_jiminy::{ use inf1_svc_ag_core::{ inf1_svc_lido_core::solido_legacy_core::TOKENKEG_PROGRAM, - inf1_svc_spl_core::instructions::sol_val_calc::SanctumSplMultiCalcAccs, - inf1_svc_spl_core::keys::sanctum_spl_multi, - inf1_svc_wsol_core::instructions::sol_val_calc::WsolCalcAccs, instructions::SvcCalcAccsAg, + inf1_svc_spl_core::{ + instructions::sol_val_calc::SanctumSplMultiCalcAccs, keys::sanctum_spl_multi, + sanctum_spl_stake_pool_core::StakePool, + }, + inf1_svc_wsol_core::instructions::sol_val_calc::WsolCalcAccs, + instructions::SvcCalcAccsAg, SvcAgTy, }; @@ -54,6 +57,21 @@ use crate::common::{ type SetSolValueCalculatorKeysBuilder = SetSolValueCalculatorIxAccs<[u8; 32], SetSolValueCalculatorIxPreKeysOwned, SvcCalcAccsAg>; +#[derive(Debug)] +struct SetSvcBaseInputs { + pool_state: PoolState, + lst_state_data: LstStateData, + lst_state_list_data: LstStateListData, + initial_svc_addr: [u8; 32], + new_balance: u64, +} + +type SanctumSplMultiStratValue = (SetSvcBaseInputs, [u8; 32], StakePool); + +type SanctumSplMultiUnauthorizedStratValue = (SetSvcBaseInputs, [u8; 32], StakePool, [u8; 32]); + +type WsolStratValue = SetSvcBaseInputs; + fn set_sol_value_calculator_ix_pre_keys_owned( admin: [u8; 32], token_program: &[u8; 32], @@ -308,55 +326,101 @@ fn set_sol_value_calculator_proptest( Ok(()) } -proptest! { - #[test] - fn set_sol_value_calculator_unauthorized_any( - (pool, lsd, stake_pool_addr, stake_pool, non_admin, initial_svc_addr, new_balance) in - (any_pool_state(AnyPoolStateArgs { +fn set_sol_value_calculator_unauthorized_strat( +) -> impl Strategy { + ( + ( + any_pool_state(AnyPoolStateArgs { bools: PoolStateBools::normal(), ..Default::default() }), any_normal_pk(), any::(), - ).prop_flat_map( - |(pool, mint_addr, spl_lamports)| ( + ) + .prop_flat_map(|(pool, mint_addr, spl_lamports)| { + ( Just(pool), any_normal_pk().prop_filter("cannot be eq mint_addr", move |x| *x != mint_addr), any_spl_stake_pool(GenStakePoolArgs { pool_mint: Some(Just(mint_addr).boxed()), - u64s: SplStakePoolU64s(NewSplStakePoolU64sBuilder::start() - .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 - .with_total_lamports(Just(spl_lamports).boxed()) - .with_pool_token_supply((spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed()) - .build().0.map(Some)), + u64s: SplStakePoolU64s( + NewSplStakePoolU64sBuilder::start() + .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 + .with_total_lamports(Just(spl_lamports).boxed()) + .with_pool_token_supply( + (spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed(), + ) + .build() + .0 + .map(Some), + ), ..Default::default() }), any_lst_state( AnyLstStateArgs { sol_value: Some((0..=pool.total_sol_value).boxed()), - pks: LstStatePks(NewLstStatePksBuilder::start() - .with_mint(mint_addr) - .with_sol_value_calculator(sanctum_spl_multi::ID) - .build().0.map(|x| Some(Just(x).boxed()))), + pks: LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(mint_addr) + .with_sol_value_calculator(sanctum_spl_multi::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }, None, ), any_normal_pk().prop_filter("cannot be eq admin", move |x| *x != pool.admin), ) - ).prop_flat_map( - |(pool, stake_pool_addr, stake_pool, lsd, non_admin)| ( + }) + .prop_flat_map(|(pool, stake_pool_addr, stake_pool, lsd, non_admin)| { + ( Just(pool), Just(lsd), Just(stake_pool_addr), Just(stake_pool), Just(non_admin), any_normal_pk(), - 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) / MAX_LAMPORTS_OVER_SUPPLY, + 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) + / MAX_LAMPORTS_OVER_SUPPLY, ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |( + (pool, lsd, stake_pool_addr, stake_pool, non_admin, initial_svc_addr, new_balance), + lsl, + )| { + ( + SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + }, + stake_pool_addr, + stake_pool, + non_admin, + ) + }, + ) +} + +proptest! { + #[test] + fn set_sol_value_calculator_unauthorized_any( + (base, stake_pool_addr, stake_pool, non_admin) in set_sol_value_calculator_unauthorized_strat(), ) { + let SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + } = base; set_sol_value_calculator_proptest(pool, lsl, lsd, non_admin, *SvcAgTy::SanctumSplMulti(()).svc_program_id(), SvcCalcAccsAg::SanctumSplMulti(SanctumSplMultiCalcAccs { stake_pool_addr }), initial_svc_addr, new_balance, [ (lsd.lst_state.mint.into(), mock_mint(raw_mint(None, None, u64::MAX, 9))), (Pubkey::new_from_array(stake_pool_addr), mock_spl_stake_pool(&stake_pool, sanctum_spl_multi::POOL_PROG_ID.into())), @@ -364,56 +428,102 @@ proptest! { } } -proptest! { - #[test] - fn set_sol_value_calculator_rebalancing_any( - (pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance) in - (any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() - .with_is_disabled(false) - .with_is_rebalancing(true) - .build().0.map(|x| Some(Just(x).boxed()))), - ..Default::default() - }), +fn set_sol_value_calculator_rebalancing_strat() -> impl Strategy +{ + ( + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() + .with_is_disabled(false) + .with_is_rebalancing(true) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), + ..Default::default() + }), any_normal_pk(), any::(), - ).prop_flat_map( - |(pool, mint_addr, spl_lamports)| ( + ) + .prop_flat_map(|(pool, mint_addr, spl_lamports)| { + ( Just(pool), any_normal_pk().prop_filter("cannot be eq mint_addr", move |x| *x != mint_addr), any_spl_stake_pool(GenStakePoolArgs { pool_mint: Some(Just(mint_addr).boxed()), - u64s: SplStakePoolU64s(NewSplStakePoolU64sBuilder::start() - .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 - .with_total_lamports(Just(spl_lamports).boxed()) - .with_pool_token_supply((spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed()) - .build().0.map(Some)), + u64s: SplStakePoolU64s( + NewSplStakePoolU64sBuilder::start() + .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 + .with_total_lamports(Just(spl_lamports).boxed()) + .with_pool_token_supply( + (spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed(), + ) + .build() + .0 + .map(Some), + ), ..Default::default() }), any_lst_state( AnyLstStateArgs { sol_value: Some((0..=pool.total_sol_value).boxed()), - pks: LstStatePks(NewLstStatePksBuilder::start() - .with_mint(mint_addr) - .with_sol_value_calculator(sanctum_spl_multi::ID) - .build().0.map(|x| Some(Just(x).boxed()))), + pks: LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(mint_addr) + .with_sol_value_calculator(sanctum_spl_multi::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }, None, ), ) - ).prop_flat_map( - |(pool, stake_pool_addr, stake_pool, lsd)| ( + }) + .prop_flat_map(|(pool, stake_pool_addr, stake_pool, lsd)| { + ( Just(pool), Just(lsd), Just(stake_pool_addr), Just(stake_pool), any_normal_pk(), - 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) / MAX_LAMPORTS_OVER_SUPPLY, + 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) + / MAX_LAMPORTS_OVER_SUPPLY, ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |((pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance), lsl)| { + ( + SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + }, + stake_pool_addr, + stake_pool, + ) + }, + ) +} + +proptest! { + #[test] + fn set_sol_value_calculator_rebalancing_any( + (base, stake_pool_addr, stake_pool) in set_sol_value_calculator_rebalancing_strat(), ) { + let SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + } = base; set_sol_value_calculator_proptest(pool, lsl, lsd, pool.admin, *SvcAgTy::SanctumSplMulti(()).svc_program_id(), SvcCalcAccsAg::SanctumSplMulti(SanctumSplMultiCalcAccs { stake_pool_addr }), initial_svc_addr, new_balance, [ ( lsd.lst_state.mint.into(), @@ -425,56 +535,101 @@ proptest! { } } -proptest! { - #[test] - fn set_sol_value_calculator_disabled_any( - (pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance) in - (any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools(NewPoolStateBoolsBuilder::start() - .with_is_disabled(true) - .with_is_rebalancing(false) - .build().0.map(|x| Some(Just(x).boxed()))), +fn set_sol_value_calculator_disabled_strat() -> impl Strategy { + ( + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools( + NewPoolStateBoolsBuilder::start() + .with_is_disabled(true) + .with_is_rebalancing(false) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }), any_normal_pk(), any::(), - ).prop_flat_map( - |(pool, mint_addr, spl_lamports)| ( + ) + .prop_flat_map(|(pool, mint_addr, spl_lamports)| { + ( Just(pool), any_normal_pk().prop_filter("cannot be eq mint_addr", move |x| *x != mint_addr), any_spl_stake_pool(GenStakePoolArgs { pool_mint: Some(Just(mint_addr).boxed()), - u64s: SplStakePoolU64s(NewSplStakePoolU64sBuilder::start() - .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 - .with_total_lamports(Just(spl_lamports).boxed()) - .with_pool_token_supply((spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed()) - .build().0.map(Some)), + u64s: SplStakePoolU64s( + NewSplStakePoolU64sBuilder::start() + .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 + .with_total_lamports(Just(spl_lamports).boxed()) + .with_pool_token_supply( + (spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed(), + ) + .build() + .0 + .map(Some), + ), ..Default::default() }), any_lst_state( AnyLstStateArgs { sol_value: Some((0..=pool.total_sol_value).boxed()), - pks: LstStatePks(NewLstStatePksBuilder::start() - .with_mint(mint_addr) - .with_sol_value_calculator(sanctum_spl_multi::ID) - .build().0.map(|x| Some(Just(x).boxed()))), + pks: LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(mint_addr) + .with_sol_value_calculator(sanctum_spl_multi::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }, None, ), ) - ).prop_flat_map( - |(pool, stake_pool_addr, stake_pool, lsd)| ( + }) + .prop_flat_map(|(pool, stake_pool_addr, stake_pool, lsd)| { + ( Just(pool), Just(lsd), Just(stake_pool_addr), Just(stake_pool), any_normal_pk(), - 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) / MAX_LAMPORTS_OVER_SUPPLY, + 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) + / MAX_LAMPORTS_OVER_SUPPLY, ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |((pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance), lsl)| { + ( + SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + }, + stake_pool_addr, + stake_pool, + ) + }, + ) +} + +proptest! { + #[test] + fn set_sol_value_calculator_disabled_any( + (base, stake_pool_addr, stake_pool) in set_sol_value_calculator_disabled_strat(), ) { + let SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + } = base; set_sol_value_calculator_proptest( pool, lsl, @@ -493,32 +648,57 @@ proptest! { } } +fn set_sol_value_calculator_wsol_strat() -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }) + .prop_flat_map(|pool| { + ( + Just(pool), + any_wsol_lst_state(AnyLstStateArgs { + sol_value: Some((0..=pool.total_sol_value).boxed()), + ..Default::default() + }), + any_normal_pk().prop_filter("cannot be eq wsol svc addr", move |x| { + *x != *SvcAgTy::Wsol(()).svc_program_id() + }), + ) + }) + .prop_flat_map(|(pool, wsol_lsd, initial_svc_addr)| { + ( + Just(pool), + Just(wsol_lsd), + Just(initial_svc_addr), + 0..=max_sol_val_no_overflow(pool.total_sol_value, wsol_lsd.lst_state.sol_value), + ) + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |((pool, wsol_lsd, initial_svc_addr, new_balance), lsl)| SetSvcBaseInputs { + pool_state: pool, + lst_state_data: wsol_lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + }, + ) +} + proptest! { #[test] fn set_sol_value_calculator_wsol_any( - (pool, wsol_lsd, initial_svc_addr, new_balance) in - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }).prop_flat_map( - |pool| ( - Just(pool), - any_wsol_lst_state(AnyLstStateArgs { - sol_value: Some((0..=pool.total_sol_value).boxed()), - ..Default::default() - }), - any_normal_pk().prop_filter("cannot be eq wsol svc addr", move |x| *x != *SvcAgTy::Wsol(()).svc_program_id()), - ) - ).prop_flat_map( - |(pool, wsol_lsd, initial_svc_addr)| ( - Just(pool), - Just(wsol_lsd), - Just(initial_svc_addr), - 0..=max_sol_val_no_overflow(pool.total_sol_value, wsol_lsd.lst_state.sol_value), - ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + base in set_sol_value_calculator_wsol_strat(), ) { + let SetSvcBaseInputs { + pool_state: pool, + lst_state_data: wsol_lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + } = base; set_sol_value_calculator_proptest( pool, lsl, @@ -534,55 +714,101 @@ proptest! { } } -proptest! { - #[test] - fn set_sol_value_calculator_sanctum_spl_multi_any( - (pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance) in - ( - any_pool_state(AnyPoolStateArgs { +fn set_sol_value_calculator_sanctum_spl_multi_strat( +) -> impl Strategy { + ( + ( + any_pool_state(AnyPoolStateArgs { bools: PoolStateBools::normal(), ..Default::default() }), any_normal_pk(), any::(), - ).prop_flat_map( - |(pool, mint_addr, spl_lamports)| ( + ) + .prop_flat_map(|(pool, mint_addr, spl_lamports)| { + ( Just(pool), any_normal_pk().prop_filter("cannot be eq mint_addr", move |x| *x != mint_addr), any_spl_stake_pool(GenStakePoolArgs { pool_mint: Some(Just(mint_addr).boxed()), - u64s: SplStakePoolU64s(NewSplStakePoolU64sBuilder::start() - .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 - .with_total_lamports(Just(spl_lamports).boxed()) - .with_pool_token_supply((spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed()) - .build().0.map(Some)), + u64s: SplStakePoolU64s( + NewSplStakePoolU64sBuilder::start() + .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 + .with_total_lamports(Just(spl_lamports).boxed()) + .with_pool_token_supply( + (spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed(), + ) + .build() + .0 + .map(Some), + ), ..Default::default() }), any_lst_state( AnyLstStateArgs { sol_value: Some((0..=pool.total_sol_value).boxed()), - pks: LstStatePks(NewLstStatePksBuilder::start() - .with_mint(mint_addr) - .with_sol_value_calculator(sanctum_spl_multi::ID) - .build().0.map(|x| Some(Just(x).boxed()))), + pks: LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(mint_addr) + .with_sol_value_calculator(sanctum_spl_multi::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }, None, ), - any_normal_pk().prop_filter("cannot be eq sanctum spl multi svc addr", move |x| *x != *SvcAgTy::SanctumSplMulti(()).svc_program_id()), - ) - ).prop_flat_map( - |(pool, stake_pool_addr, stake_pool, lsd, initial_svc_addr)| ( - Just(pool), - Just(lsd), - Just(stake_pool_addr), - Just(stake_pool), - Just(initial_svc_addr), - 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) / MAX_LAMPORTS_OVER_SUPPLY, + any_normal_pk() + .prop_filter("cannot be eq sanctum spl multi svc addr", move |x| { + *x != *SvcAgTy::SanctumSplMulti(()).svc_program_id() + }), ) + }) + .prop_flat_map( + |(pool, stake_pool_addr, stake_pool, lsd, initial_svc_addr)| { + ( + Just(pool), + Just(lsd), + Just(stake_pool_addr), + Just(stake_pool), + Just(initial_svc_addr), + 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) + / MAX_LAMPORTS_OVER_SUPPLY, + ) + }, ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |((pool, lsd, stake_pool_addr, stake_pool, initial_svc_addr, new_balance), lsl)| { + ( + SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + }, + stake_pool_addr, + stake_pool, + ) + }, + ) +} + +proptest! { + #[test] + fn set_sol_value_calculator_sanctum_spl_multi_any( + (base, stake_pool_addr, stake_pool) in set_sol_value_calculator_sanctum_spl_multi_strat(), ) { + let SetSvcBaseInputs { + pool_state: pool, + lst_state_data: lsd, + lst_state_list_data: lsl, + initial_svc_addr, + new_balance, + } = base; set_sol_value_calculator_proptest(pool, lsl, lsd, pool.admin, *SvcAgTy::SanctumSplMulti(()).svc_program_id(), SvcCalcAccsAg::SanctumSplMulti(SanctumSplMultiCalcAccs { stake_pool_addr }), initial_svc_addr, new_balance, [ (lsd.lst_state.mint.into(), mock_mint(raw_mint(None, None, u64::MAX, 9))), (Pubkey::new_from_array(stake_pool_addr), mock_spl_stake_pool(&stake_pool, sanctum_spl_multi::POOL_PROG_ID.into())), diff --git a/controller/program/tests/tests/rebalance/chain.rs b/controller/program/tests/tests/rebalance/chain.rs index 5af89bfa..2a791e01 100644 --- a/controller/program/tests/tests/rebalance/chain.rs +++ b/controller/program/tests/tests/rebalance/chain.rs @@ -898,12 +898,14 @@ fn unauthorized_rebalance_authority() { assert_jiminy_prog_err(&result.program_result, INVALID_ARGUMENT); } +fn various_amounts_strat() -> impl Strategy { + (1u64..=1_000_000_000, 2u64..=100, 2u64..=100) +} + proptest! { #[test] fn rebalance_transaction_various_amounts_any( - amount in 1u64..=1_000_000_000, - out_reserve_multiplier in 2u64..=100, - inp_reserve_multiplier in 2u64..=100, + (amount, out_reserve_multiplier, inp_reserve_multiplier) in various_amounts_strat(), ) { let out_reserves = amount.saturating_mul(out_reserve_multiplier); let inp_reserves = amount.saturating_mul(inp_reserve_multiplier); diff --git a/controller/program/tests/tests/sync_sol_value.rs b/controller/program/tests/tests/sync_sol_value.rs index 7eadead4..cc5a806a 100644 --- a/controller/program/tests/tests/sync_sol_value.rs +++ b/controller/program/tests/tests/sync_sol_value.rs @@ -222,29 +222,37 @@ fn sync_sol_value_wsol_proptest( Ok(()) } +fn wsol_sync_strat() -> impl Strategy { + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }) + .prop_flat_map(|pool| { + ( + Just(pool), + any_wsol_lst_state(AnyLstStateArgs { + sol_value: Some((0..=pool.total_sol_value).boxed()), + ..Default::default() + }), + ) + }) + .prop_flat_map(|(pool, wsol_lsd)| { + ( + Just(pool), + Just(wsol_lsd), + 0..=max_sol_val_no_overflow(pool.total_sol_value, wsol_lsd.lst_state.sol_value), + ) + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map(|((pool, wsol_lsd, new_balance), lsl)| (pool, wsol_lsd, new_balance, lsl)) +} + proptest! { #[test] fn sync_sol_value_wsol_any( - (pool, wsol_lsd, new_balance) in - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }).prop_flat_map( - |pool| ( - Just(pool), - any_wsol_lst_state(AnyLstStateArgs { - sol_value: Some((0..=pool.total_sol_value).boxed()), - ..Default::default() - }), - ) - ).prop_flat_map( - |(pool, wsol_lsd)| ( - Just(pool), - Just(wsol_lsd), - 0..=max_sol_val_no_overflow(pool.total_sol_value, wsol_lsd.lst_state.sol_value), - ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + (pool, wsol_lsd, new_balance, lsl) in wsol_sync_strat(), ) { sync_sol_value_wsol_proptest(pool, lsl, wsol_lsd, new_balance).unwrap(); } @@ -326,52 +334,84 @@ fn sync_sol_value_sanctum_spl_multi_proptest( Ok(()) } -proptest! { - #[test] - fn sync_sol_value_sanctum_spl_multi_any( - (pool, lsd, stake_pool_addr, stake_pool, new_balance) in - ( - any_pool_state(AnyPoolStateArgs { - bools: PoolStateBools::normal(), - ..Default::default() - }), - any_normal_pk(), - any::(), - ).prop_flat_map( - |(pool, mint_addr, spl_lamports)| ( +fn sanctum_spl_multi_sync_strat() -> impl Strategy< + Value = ( + PoolState, + LstStateData, + [u8; 32], + StakePool, + u64, + LstStateListData, + ), +> { + ( + ( + any_pool_state(AnyPoolStateArgs { + bools: PoolStateBools::normal(), + ..Default::default() + }), + any_normal_pk(), + any::(), + ) + .prop_flat_map(|(pool, mint_addr, spl_lamports)| { + ( Just(pool), any_normal_pk().prop_filter("cannot be eq mint_addr", move |x| *x != mint_addr), any_spl_stake_pool(GenStakePoolArgs { pool_mint: Some(Just(mint_addr).boxed()), - u64s: SplStakePoolU64s(NewSplStakePoolU64sBuilder::start() - .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 - .with_total_lamports(Just(spl_lamports).boxed()) - .with_pool_token_supply((spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed()) - .build().0.map(Some)), + u64s: SplStakePoolU64s( + NewSplStakePoolU64sBuilder::start() + .with_last_update_epoch(Just(0).boxed()) // mollusk clock defaults to epoch 0 + .with_total_lamports(Just(spl_lamports).boxed()) + .with_pool_token_supply( + (spl_lamports / MAX_LAMPORTS_OVER_SUPPLY..=u64::MAX).boxed(), + ) + .build() + .0 + .map(Some), + ), ..Default::default() }), any_lst_state( AnyLstStateArgs { sol_value: Some((0..=pool.total_sol_value).boxed()), - pks: LstStatePks(NewLstStatePksBuilder::start() - .with_mint(mint_addr) - .with_sol_value_calculator(sanctum_spl_multi::ID) - .build().0.map(|x| Some(Just(x).boxed()))), + pks: LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(mint_addr) + .with_sol_value_calculator(sanctum_spl_multi::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ), ..Default::default() }, None, ), ) - ).prop_flat_map( - |(pool, stake_pool_addr, stake_pool, lsd)| ( + }) + .prop_flat_map(|(pool, stake_pool_addr, stake_pool, lsd)| { + ( Just(pool), Just(lsd), Just(stake_pool_addr), Just(stake_pool), - 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) / MAX_LAMPORTS_OVER_SUPPLY, + 0..=max_sol_val_no_overflow(pool.total_sol_value, lsd.lst_state.sol_value) + / MAX_LAMPORTS_OVER_SUPPLY, ) - ), - lsl in any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + }), + any_lst_state_list(Default::default(), None, 0..=MAX_LST_STATES), + ) + .prop_map( + |((pool, lsd, stake_pool_addr, stake_pool, new_balance), lsl)| { + (pool, lsd, stake_pool_addr, stake_pool, new_balance, lsl) + }, + ) +} + +proptest! { + #[test] + fn sync_sol_value_sanctum_spl_multi_any( + (pool, lsd, stake_pool_addr, stake_pool, new_balance, lsl) in sanctum_spl_multi_sync_strat(), ) { sync_sol_value_sanctum_spl_multi_proptest( pool,