diff --git a/controller/core/src/svc.rs b/controller/core/src/svc.rs index 8a341795..b564a8e4 100644 --- a/controller/core/src/svc.rs +++ b/controller/core/src/svc.rs @@ -70,60 +70,57 @@ impl InfCalc { /// If withheld is nonzero, then zero will be returned; /// value should be nonzero again after waiting some time. #[inline] - pub const fn sol_to_inf(&self, sol: u64) -> Option { - let r = match self.supply_over_lp_due() { + pub const fn inf_to_sol(&self, inf: u64) -> Option { + let r = match self.lp_due_over_supply() { None => return None, Some(r) => r, }; - let r = if r.n == 0 || (r.d == 0 && *self.pool_lamports.withheld() == 0) { - Ratio::::ONE - } else { - r - }; - Floor(r).apply(sol) + r.apply(inf) } - /// Edge cases: same as [`Self::sol_to_inf`] + /// Edge cases: same as [`Self::inf_to_sol`] #[inline] - pub const fn inf_to_sol(&self, inf: u64) -> Option { + pub const fn sol_to_inf(&self, sol: u64) -> Option> { let r = match self.lp_due_over_supply() { None => return None, Some(r) => r, }; - let r = if r.d == 0 || (r.n == 0 && *self.pool_lamports.withheld() == 0) { - Ratio::::ONE - } else { - r + let range = match r.reverse_est(sol) { + None => return None, + Some(x) => x, }; - Floor(r).apply(inf) + Some(if *range.start() > *range.end() { + *range.end()..=*range.start() + } else { + range + }) } /// # Returns - /// (inf_supply / lamports_due_to_lp) + /// (lamports_due_to_lp / inf_supply), with the following special-cases + /// that returns 1.0: + /// - LP supply = 0 + /// - LP due sol value = 0 & withheld = 0 /// - /// `None` if pool is insolvent for LPers (lp_due is negative) - #[inline] - pub const fn supply_over_lp_due(&self) -> Option> { - match self.pool_lamports.lp_due_checked() { - None => None, - Some(d) => Some(Ratio { - n: self.mint_supply, - d, - }), - } - } - - /// # Returns - /// (lamports_due_to_lp / inf_supply) + /// See doc on [`Self::inf_to_sol`] on why. /// /// `None` if pool is insolvent for LPers (lp_due is negative) #[inline] - pub const fn lp_due_over_supply(&self) -> Option> { - match self.supply_over_lp_due() { - None => None, - // TODO: add .inv() to sanctum-u64-ratio - Some(Ratio { n, d }) => Some(Ratio { n: d, d: n }), - } + pub const fn lp_due_over_supply(&self) -> Option>> { + let r = match self.pool_lamports.lp_due_checked() { + None => return None, + Some(n) => Ratio { + n, + d: self.mint_supply, + }, + }; + Some(Floor( + if r.d == 0 || (r.n == 0 && *self.pool_lamports.withheld() == 0) { + Ratio::::ONE + } else { + r + }, + )) } } @@ -166,7 +163,7 @@ impl InfCalc { pub const fn svc_sol_to_lst(&self, sol: u64) -> Result, InfCalcErr> { match self.sol_to_inf(sol) { None => Err(InfCalcErr::Math), - Some(x) => Ok(x..=x), + Some(x) => Ok(x), } } } @@ -234,3 +231,66 @@ impl SolValCalcAccs for InfDummyCalcAccs { self.svc_suf_is_signer() } } + +#[cfg(test)] +mod tests { + use std::convert::identity; + + use proptest::prelude::*; + + use crate::typedefs::pool_sv::test_utils::pool_sv_lamports_invar_strat; + + use super::*; + + /// - PoolSvLamports solvency invariant respected + fn any_calc() -> impl Strategy { + ( + any::(), + any::() + .prop_map(pool_sv_lamports_invar_strat) + .prop_flat_map(identity), + ) + .prop_map(|(mint_supply, pool_lamports)| InfCalc { + pool_lamports, + mint_supply, + }) + } + + proptest! { + #[test] + fn lp_due_over_supply_is_never_zero(calc in any_calc()) { + let r = calc.lp_due_over_supply().unwrap(); + assert!(!r.0.is_zero()); + } + } + + // make sure we've handled the `Ratio::reverse_est` + // case correctly + fn assert_valid_range(r: &RangeInclusive) { + assert!(r.start() <= r.end(), "{r:?}"); + } + + fn assert_err_bound(val: u64, r: &RangeInclusive) { + assert!(r.contains(&val), "{val} {r:?}"); + } + + proptest! { + #[test] + fn sol_to_inf_rt_errbound( + val: u64, + calc in any_calc(), + ) { + if let Some(inf) = calc.sol_to_inf(val) { + let [min_rt, max_rt] = + [inf.start(), inf.end()].map(|x| calc.inf_to_sol(*x).unwrap()); + assert_err_bound(val, &(min_rt..=max_rt)); + assert_valid_range(&inf); + } + if let Some(sol) = calc.inf_to_sol(val) { + let rt = calc.sol_to_inf(sol).unwrap(); + assert_err_bound(val, &rt); + assert_valid_range(&rt); + } + } + } +} diff --git a/controller/core/src/typedefs/pool_sv.rs b/controller/core/src/typedefs/pool_sv.rs index f04dad94..3d132bf3 100644 --- a/controller/core/src/typedefs/pool_sv.rs +++ b/controller/core/src/typedefs/pool_sv.rs @@ -72,3 +72,26 @@ impl PoolSvMutRefs<'_> { self.0.iter_mut().zip(vals.0).for_each(|(r, x)| **r = x); } } + +#[cfg(test)] +pub mod test_utils { + use inf1_test_utils::bals_from_supply; + use proptest::prelude::*; + + use super::*; + + /// Gens PoolSvLamports where the invariant + /// + /// total_sol_value >= protocol_fee_lamports + withheld_lamports + /// + /// holds + pub fn pool_sv_lamports_invar_strat(tsv: u64) -> impl Strategy { + bals_from_supply(tsv).prop_map(move |([withheld, protocol_fee], _rem)| { + NewPoolSvBuilder::start() + .with_protocol_fee(protocol_fee) + .with_withheld(withheld) + .with_total(tsv) + .build() + }) + } +} diff --git a/controller/core/src/yields/update.rs b/controller/core/src/yields/update.rs index cb8dc040..3770c8bf 100644 --- a/controller/core/src/yields/update.rs +++ b/controller/core/src/yields/update.rs @@ -56,28 +56,12 @@ impl UpdateYield { #[cfg(test)] mod tests { - use inf1_test_utils::bals_from_supply; use proptest::prelude::*; - use crate::typedefs::pool_sv::NewPoolSvBuilder; + use crate::typedefs::pool_sv::test_utils::pool_sv_lamports_invar_strat; use super::*; - /// Gens PoolSvLamports where the invariant - /// - /// total_sol_value >= protocol_fee_lamports + withheld_lamports - /// - /// holds - fn pool_sv_lamports_invar_strat(tsv: u64) -> impl Strategy { - bals_from_supply(tsv).prop_map(move |([withheld, protocol_fee], _rem)| { - NewPoolSvBuilder::start() - .with_protocol_fee(protocol_fee) - .with_withheld(withheld) - .with_total(tsv) - .build() - }) - } - fn any_update_yield_strat() -> impl Strategy { any::() .prop_flat_map(|old_tsv| (any::(), pool_sv_lamports_invar_strat(old_tsv))) diff --git a/controller/program/src/instructions/protocol_fee/withdraw_protocol_fees/v2.rs b/controller/program/src/instructions/protocol_fee/withdraw_protocol_fees/v2.rs index 12caec49..2b3f69ec 100644 --- a/controller/program/src/instructions/protocol_fee/withdraw_protocol_fees/v2.rs +++ b/controller/program/src/instructions/protocol_fee/withdraw_protocol_fees/v2.rs @@ -84,9 +84,10 @@ pub fn process_withdraw_protocol_fees_v2( mint_supply: inf_token_supply, }; - let inf_to_mint = inf_calc + let inf_to_mint = *inf_calc .sol_to_inf(protocol_fee_lamports) - .ok_or(Inf1CtlCustomProgErr(Inf1CtlErr::MathError))?; + .ok_or(Inf1CtlCustomProgErr(Inf1CtlErr::MathError))? + .start(); if inf_to_mint == 0 { return Ok(()); diff --git a/controller/program/tests/common/mollusk.rs b/controller/program/tests/common/mollusk.rs index 6bcb715c..f0197dd2 100644 --- a/controller/program/tests/common/mollusk.rs +++ b/controller/program/tests/common/mollusk.rs @@ -1,6 +1,10 @@ +use std::cell::RefCell; + use inf1_test_utils::mollusk_inf_local_ctl; use mollusk_svm::Mollusk; thread_local! { - pub static SVM: Mollusk = mollusk_inf_local_ctl() + pub static SVM: Mollusk = mollusk_inf_local_ctl(); + + pub static SVM_MUT: RefCell = RefCell::new(mollusk_inf_local_ctl()); } diff --git a/controller/program/tests/tests/admin/add_lst.rs b/controller/program/tests/tests/admin/add_lst.rs index cb0f37ea..6bd1f291 100644 --- a/controller/program/tests/tests/admin/add_lst.rs +++ b/controller/program/tests/tests/admin/add_lst.rs @@ -82,10 +82,6 @@ fn assert_correct_add( token_program: &[u8; 32], expected_sol_value_calculator: &[u8; 32], ) { - let lamports_bef: u128 = bef.values().map(|acc| acc.lamports as u128).sum(); - let lamports_aft: u128 = aft.values().map(|acc| acc.lamports as u128).sum(); - assert_eq!(lamports_bef, lamports_aft); - let (_, pool_reserves_bump) = find_pool_reserves_ata(token_program, mint); let (_, protocol_fee_accumulator_bump) = find_protocol_fee_accumulator_ata(token_program, mint); diff --git a/controller/program/tests/tests/protocol_fee/withdraw_protocol_fees/v2.rs b/controller/program/tests/tests/protocol_fee/withdraw_protocol_fees/v2.rs index 60e5394a..865cb6d8 100644 --- a/controller/program/tests/tests/protocol_fee/withdraw_protocol_fees/v2.rs +++ b/controller/program/tests/tests/protocol_fee/withdraw_protocol_fees/v2.rs @@ -135,9 +135,10 @@ fn withdraw_protocol_fees_v2_test( pool_lamports: PoolSvLamports::from_pool_state_v2(&pool_state_bef), mint_supply: inf_mint_bef.supply(), }; - let expected_minted = inf_calc + let expected_minted = *inf_calc .sol_to_inf(pool_state_bef.protocol_fee_lamports) - .unwrap(); + .unwrap() + .start(); assert_token_acc_diffs( withdraw_to_bef, diff --git a/controller/program/tests/tests/swap/common/asserts.rs b/controller/program/tests/tests/swap/common/asserts.rs index 01798691..41b5e980 100644 --- a/controller/program/tests/tests/swap/common/asserts.rs +++ b/controller/program/tests/tests/swap/common/asserts.rs @@ -233,6 +233,12 @@ fn assert_accs_swap( out_svc.neg(), tsv_inc ); + + // sum sol value = total_sol_value invariant + assert_eq!( + list_aft.iter().map(|s| s.sol_value).sum::(), + ps_aft.total_sol_value + ); } fn assert_pool_token_movements_add_liq( @@ -310,6 +316,12 @@ fn assert_accs_liq( // assert everything else other than sol value didnt change assert_diffs_lst_state_list(list_diffs.build(), list_aft_hla, list_aft); + + // sum sol value = total_sol_value invariant + assert_eq!( + list_aft.iter().map(|s| s.sol_value).sum::(), + ps_aft.total_sol_value + ); } /// assert redemption rate of INF did not decrease after add/remove liq diff --git a/controller/program/tests/tests/swap/common/mod.rs b/controller/program/tests/tests/swap/common/mod.rs index b6cefe06..a046c281 100644 --- a/controller/program/tests/tests/swap/common/mod.rs +++ b/controller/program/tests/tests/swap/common/mod.rs @@ -1,7 +1,9 @@ mod accounts; mod asserts; mod derives; +mod strats; pub use accounts::*; pub use asserts::*; pub use derives::*; +pub use strats::*; diff --git a/controller/program/tests/tests/swap/common/strats.rs b/controller/program/tests/tests/swap/common/strats.rs new file mode 100644 index 00000000..3741119f --- /dev/null +++ b/controller/program/tests/tests/swap/common/strats.rs @@ -0,0 +1,60 @@ +use inf1_ctl_jiminy::{ + accounts::{lst_state_list::LstStatePackedList, pool_state::PoolStateV2}, + typedefs::pool_sv::PoolSvMutRefs, +}; +use inf1_svc_ag_core::inf1_svc_wsol_core; +use inf1_test_utils::{ + any_lst_state, any_lst_state_list, any_pool_state_v2, pool_sv_lamports_solvent_strat, + AnyLstStateArgs, LstStateListData, LstStatePks, NewLstStatePksBuilder, PoolStateV2FtaStrat, + WSOL_MINT, +}; +use proptest::prelude::*; + +pub fn wsol_lst_state_pks() -> LstStatePks>> { + LstStatePks( + NewLstStatePksBuilder::start() + .with_mint(WSOL_MINT.to_bytes()) + .with_sol_value_calculator(inf1_svc_wsol_core::ID) + .build() + .0 + .map(|x| Some(Just(x).boxed())), + ) +} + +/// ps_args.u64s is ignored for pool sv lamport fields +/// in order to maintain invariant that sum of lst_state_list.sol_value +/// = pool_state.total_sol_value +/// +/// Currently does not include other entries in lst_state_list to not have to +/// deal with sum of total sol values overflowing u64 +pub fn swap_prog_accs_strat( + lst_args: [AnyLstStateArgs; N], + ps_args: PoolStateV2FtaStrat, +) -> impl Strategy { + ( + lst_args.map(|a| any_lst_state(a, None)), + any_lst_state_list(Default::default(), None, 0..=0), + any_pool_state_v2(ps_args), + ) + .prop_flat_map(|(lsds, mut lsl, ps)| { + let idxs = lsds.map(|lsd| lsl.upsert(lsd)); + + let tsv = LstStatePackedList::of_acc_data(&lsl.lst_state_list) + .unwrap() + .0 + .iter() + .map(|s| s.into_lst_state().sol_value) + .sum::(); + + ( + pool_sv_lamports_solvent_strat(tsv), + Just(idxs), + Just(lsl), + Just(ps), + ) + }) + .prop_map(move |(psv, idxs, lsl, mut ps)| { + PoolSvMutRefs::from_pool_state_v2(&mut ps).update(psv); + (idxs, lsl, ps) + }) +} diff --git a/controller/program/tests/tests/swap/v1/add_liq.rs b/controller/program/tests/tests/swap/v1/add_liq.rs index b4112207..8577d4f6 100644 --- a/controller/program/tests/tests/swap/v1/add_liq.rs +++ b/controller/program/tests/tests/swap/v1/add_liq.rs @@ -137,7 +137,7 @@ fn jupsol_add_liq_fixtures() -> IxPreAccs<(Pubkey, Account)> { #[test] fn add_liq_jupsol_fixture() { - let amount = 12_049; + let amount = 10_000; let prefix_am = jupsol_add_liq_fixtures(); let prefix_keys = IxPreAccs(prefix_am.0.each_ref().map(|(addr, _)| addr.to_bytes())); @@ -166,9 +166,9 @@ fn add_liq_jupsol_fixture() { expect![[r#" ( - 12049, - 10002, - 121, + 10000, + 4950, + 101, ) "#]] .assert_debug_eq(&(inp, out, fee)); diff --git a/controller/program/tests/tests/swap/v1/rem_liq.rs b/controller/program/tests/tests/swap/v1/rem_liq.rs index c6da23b1..2242caf3 100644 --- a/controller/program/tests/tests/swap/v1/rem_liq.rs +++ b/controller/program/tests/tests/swap/v1/rem_liq.rs @@ -138,7 +138,7 @@ fn jupsol_rem_liq_fixtures() -> IxPreAccs<(Pubkey, Account)> { #[test] fn rem_liq_jupsol_fixture() { - let amount = 8_436; + let amount = 10_000; let prefix_am = jupsol_rem_liq_fixtures(); let prefix_keys = IxPreAccs(prefix_am.0.each_ref().map(|(addr, _)| addr.to_bytes())); @@ -167,9 +167,9 @@ fn rem_liq_jupsol_fixture() { expect![[r#" ( - 8436, - 9997, - 79, + 10000, + 19877, + 157, ) "#]] .assert_debug_eq(&(inp, out, fee)); diff --git a/controller/program/tests/tests/swap/v2/exact_in/add_liq.rs b/controller/program/tests/tests/swap/v2/exact_in/add_liq.rs index 49e529b7..9300af43 100644 --- a/controller/program/tests/tests/swap/v2/exact_in/add_liq.rs +++ b/controller/program/tests/tests/swap/v2/exact_in/add_liq.rs @@ -1,25 +1,41 @@ use expect_test::expect; use inf1_ctl_jiminy::{ - instructions::swap::v2::{exact_out::NewSwapExactOutV2IxPreAccsBuilder, IxPreAccs}, + accounts::pool_state::PoolStateV2Addrs, + instructions::swap::v2::{exact_in::NewSwapExactInV2IxPreAccsBuilder, IxPreAccs}, + keys::{LST_STATE_LIST_ID, POOL_STATE_ID}, svc::InfDummyCalcAccs, }; use inf1_pp_ag_core::{PricingAg, PricingAgTy}; use inf1_std::quote::Quote; -use inf1_svc_ag_core::{instructions::SvcCalcAccsAg, SvcAg, SvcAgTy}; +use inf1_svc_ag_core::{ + inf1_svc_wsol_core::instructions::sol_val_calc::WsolCalcAccs, instructions::SvcCalcAccsAg, + SvcAg, SvcAgTy, +}; use inf1_test_utils::{ - flatslab_fixture_suf_accs, jupsol_fixture_svc_suf_accs, KeyedUiAccount, JUPSOL_FIXTURE_LST_IDX, + bals_from_supply, flatslab_fixture_suf_accs, jupsol_fixture_svc_suf_accs, + lst_state_list_account, mock_mint, mock_sys_acc, mock_token_acc, mollusk_with_clock_override, + n_distinct_normal_pks, pool_state_v2_account, + pool_state_v2_u64s_with_last_release_slot_bef_incl, pool_state_v2_u8_bools_normal_strat, + raw_mint, raw_token_acc, reasonable_flatslab_strat_for_mints, silence_mollusk_logs, AccountMap, + AnyLstStateArgs, ClockArgs, ClockU64s, KeyedUiAccount, PoolStateV2FtaStrat, + JUPSOL_FIXTURE_LST_IDX, WSOL_MINT, }; use jiminy_cpi::program_error::ProgramError; +use proptest::prelude::*; +use solana_pubkey::Pubkey; -use crate::{common::SVM, tests::swap::common::fill_swap_prog_accs}; +use crate::{ + common::{SVM, SVM_MUT}, + tests::swap::common::{fill_swap_prog_accs, swap_prog_accs_strat, wsol_lst_state_pks}, +}; use super::{swap_exact_in_v2_test, Accs, Args}; #[test] fn swap_exact_in_v2_jupsol_add_liq_fixture() { - let amount = 12_049; + let amount = 10_000; let prefix_am = IxPreAccs( - NewSwapExactOutV2IxPreAccsBuilder::start() + NewSwapExactInV2IxPreAccsBuilder::start() .with_signer("jupsol-token-acc-owner") .with_pool_state("pool-state") .with_lst_state_list("lst-state-list") @@ -67,10 +83,141 @@ fn swap_exact_in_v2_jupsol_add_liq_fixture() { expect![[r#" ( - 12049, - 10002, - 121, + 10000, + 4950, + 101, ) "#]] .assert_debug_eq(&(inp, out, fee)); } + +fn add_liq_wsol_zero_inf_strat() -> impl Strategy { + let sol_val_and_inp_amt = bals_from_supply::<2>(u64::MAX).prop_map(|(bals, _)| bals); + + (any::(), sol_val_and_inp_amt) + .prop_flat_map(|(curr_slot, [sol_val, inp_amt])| { + ( + n_distinct_normal_pks(), + swap_prog_accs_strat( + [AnyLstStateArgs { + pks: wsol_lst_state_pks(), + sol_value: Some(Just(sol_val).boxed()), + is_input_disabled: Some(Just(false).boxed()), + ..Default::default() + }], + PoolStateV2FtaStrat { + u64s: pool_state_v2_u64s_with_last_release_slot_bef_incl( + Default::default(), + curr_slot, + ), + u8_bools: pool_state_v2_u8_bools_normal_strat(), + addrs: PoolStateV2Addrs::default().with_pricing_program(Some( + Just(*PricingAgTy::FlatSlab(()).program_id()).boxed(), + )), + ..Default::default() + }, + ) + .prop_flat_map(|([idx], lsl, ps)| { + ( + reasonable_flatslab_strat_for_mints( + [ps.lp_token_mint, WSOL_MINT.to_bytes()] + .into_iter() + .collect(), + ), + Just((idx, lsl, ps)), + ) + }), + Just(curr_slot), + Just((sol_val, inp_amt)), + ) + }) + .prop_map( + |( + [signer, inp_acc, out_acc], + ((pp_accs, pp_am), (idx, lsl, ps)), + curr_slot, + (wsol_sol_val, inp_amt), + )| { + let lp_mint = ( + Pubkey::new_from_array(ps.lp_token_mint), + // always 0 supply + mock_mint(raw_mint(Some(POOL_STATE_ID), None, 0, 9)), + ); + let accounts = NewSwapExactInV2IxPreAccsBuilder::start() + .with_signer((signer.into(), mock_sys_acc(1_000_000_000))) + .with_inp_acc(( + inp_acc.into(), + mock_token_acc(raw_token_acc(WSOL_MINT.to_bytes(), signer, inp_amt)), + )) + .with_out_acc(( + out_acc.into(), + mock_token_acc(raw_token_acc(ps.lp_token_mint, signer, 0)), + )) + .with_inp_mint((WSOL_MINT, mock_mint(raw_mint(None, None, u64::MAX, 9)))) + .with_inp_pool_reserves(( + lsl.all_pool_reserves[WSOL_MINT.as_array()].into(), + mock_token_acc(raw_token_acc( + WSOL_MINT.to_bytes(), + POOL_STATE_ID, + wsol_sol_val, + )), + )) + .with_inp_token_program(mollusk_svm_programs_token::token::keyed_account()) + .with_out_mint(lp_mint.clone()) + .with_out_pool_reserves(lp_mint) + .with_out_token_program(mollusk_svm_programs_token::token::keyed_account()) + .with_pool_state((POOL_STATE_ID.into(), pool_state_v2_account(ps))) + .with_lst_state_list(( + LST_STATE_LIST_ID.into(), + lst_state_list_account(lsl.lst_state_list), + )) + .build(); + let ix_prefix = IxPreAccs(accounts.0.each_ref().map(|(pk, _)| pk.to_bytes())); + + let accs = Accs { + ix_prefix, + inp_calc_prog: *SvcAgTy::Wsol(()).svc_program_id(), + inp_calc: SvcAg::Wsol(WsolCalcAccs), + out_calc_prog: inf1_ctl_jiminy::ID, + out_calc: SvcCalcAccsAg::Inf(InfDummyCalcAccs), + pricing_prog: *PricingAgTy::FlatSlab(()).program_id(), + pricing: PricingAg::FlatSlab(pp_accs), + }; + let args = Args { + inp_lst_index: idx.try_into().unwrap(), + out_lst_index: u32::MAX, + limit: 0, + amount: inp_amt, + accs, + }; + + let mut bef = accounts.0.into_iter().chain(pp_am).collect(); + fill_swap_prog_accs(&mut bef, &accs); + + (curr_slot, args, bef) + }, + ) +} + +proptest! { + #[test] + fn swap_exact_in_v2_wsol_add_from_zero_lp_supply( + (slot, args, bef) in add_liq_wsol_zero_inf_strat() + ) { + silence_mollusk_logs(); + + let quote = SVM_MUT.with_borrow_mut( + |svm| mollusk_with_clock_override( + svm, + &ClockArgs { + u64s: ClockU64s::default().with_slot(Some(slot)), + ..Default::default() + }, + |svm| swap_exact_in_v2_test(svm, &args, &bef, None::).unwrap(), + ) + ); + // since we're adding from 0 and wsol=sol, + // we should be getting 1:1 minting + prop_assert_eq!(quote.inp, quote.out + quote.fee); + } +} diff --git a/controller/program/tests/tests/swap/v2/exact_in/rem_liq.rs b/controller/program/tests/tests/swap/v2/exact_in/rem_liq.rs index 5980db88..fb4caabd 100644 --- a/controller/program/tests/tests/swap/v2/exact_in/rem_liq.rs +++ b/controller/program/tests/tests/swap/v2/exact_in/rem_liq.rs @@ -17,7 +17,7 @@ use super::{swap_exact_in_v2_test, Accs, Args}; #[test] fn swap_exact_in_v2_jupsol_rem_liq_fixture() { - let amount = 8_436; + let amount = 10_000; let prefix_am = IxPreAccs( NewSwapExactOutV2IxPreAccsBuilder::start() .with_signer("inf-token-acc-owner") @@ -67,9 +67,9 @@ fn swap_exact_in_v2_jupsol_rem_liq_fixture() { expect![[r#" ( - 8436, - 9997, - 79, + 10000, + 19877, + 157, ) "#]] .assert_debug_eq(&(inp, out, fee)); diff --git a/controller/program/tests/tests/swap/v2/exact_out/add_liq.rs b/controller/program/tests/tests/swap/v2/exact_out/add_liq.rs index 3a488cb0..56283b0d 100644 --- a/controller/program/tests/tests/swap/v2/exact_out/add_liq.rs +++ b/controller/program/tests/tests/swap/v2/exact_out/add_liq.rs @@ -17,7 +17,7 @@ use super::{swap_exact_out_v2_test, Accs, Args}; #[test] fn swap_exact_out_v2_jupsol_add_liq_fixture() { - let amount = 10_000; + let amount = 4_950; let prefix_am = IxPreAccs( NewSwapExactOutV2IxPreAccsBuilder::start() .with_signer("jupsol-token-acc-owner") @@ -66,9 +66,9 @@ fn swap_exact_out_v2_jupsol_add_liq_fixture() { expect![[r#" ( - 12049, - 10000, - 121, + 10003, + 4950, + 101, ) "#]] .assert_debug_eq(&(inp, out, fee)); diff --git a/controller/program/tests/tests/swap/v2/exact_out/rem_liq.rs b/controller/program/tests/tests/swap/v2/exact_out/rem_liq.rs index 665d26b0..ce904d4f 100644 --- a/controller/program/tests/tests/swap/v2/exact_out/rem_liq.rs +++ b/controller/program/tests/tests/swap/v2/exact_out/rem_liq.rs @@ -17,7 +17,7 @@ use super::{swap_exact_out_v2_test, Accs, Args}; #[test] fn swap_exact_out_v2_jupsol_rem_liq_fixture() { - let amount = 10_000; + let amount = 19_877; let prefix_am = IxPreAccs( NewSwapExactOutV2IxPreAccsBuilder::start() .with_signer("inf-token-acc-owner") @@ -66,9 +66,9 @@ fn swap_exact_out_v2_jupsol_rem_liq_fixture() { expect![[r#" ( - 8436, 10000, - 79, + 19877, + 157, ) "#]] .assert_debug_eq(&(inp, out, fee)); diff --git a/test-fixtures/inf-mint.json b/test-fixtures/inf-mint.json index 4d7c0327..a84d0fde 100644 --- a/test-fixtures/inf-mint.json +++ b/test-fixtures/inf-mint.json @@ -3,7 +3,7 @@ "account": { "lamports": 31488619, "data": [ - "AQAAAI3YcqO3Fd7R1GA0P/W6SigQLjkCRyWJX+vHqceXITPT8w211Jj7AQAJAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "AQAAAI3YcqO3Fd7R1GA0P/W6SigQLjkCRyWJX+vHqceXITPTACA9iHktAAAJAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "base64" ], "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", @@ -11,4 +11,4 @@ "rentEpoch": 18446744073709551615, "space": 82 } -} \ No newline at end of file +} diff --git a/test-fixtures/pool-state.json b/test-fixtures/pool-state.json index ed30ef73..b1155d80 100644 --- a/test-fixtures/pool-state.json +++ b/test-fixtures/pool-state.json @@ -3,7 +3,7 @@ "account": { "lamports": 939704401, "data": [ - "aatZ6IyiAgDoA+gDAQAAAG88zq88cK7feT2e99JLAeub9J1heJZzUAPXKBXoXdtx4oftndHhX1YKVb7SCuZg7OkYfR9kkzw35PeEt8kTMgbKvUqRKRf0alKsqJTt8k4Ky7YNgu3i9qC30MtiePqfrgzPtIBvFaPPksJb9UynxdIQDMvDwcaW1vQToER3w2L+R1eJn7i+26KHeKrNZ+Vo5zRwzOkLzVMrbLYYKXYogk4=", + "7EEOvVplAADoA+gDAQAAAG88zq88cK7feT2e99JLAeub9J1heJZzUAPXKBXoXdtx4oftndHhX1YKVb7SCuZg7OkYfR9kkzw35PeEt8kTMgbKvUqRKRf0alKsqJTt8k4Ky7YNgu3i9qC30MtiePqfrgzPtIBvFaPPksJb9UynxdIQDMvDwcaW1vQToER3w2L+R1eJn7i+26KHeKrNZ+Vo5zRwzOkLzVMrbLYYKXYogk4=", "base64" ], "owner": "5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx", diff --git a/test-utils/src/accounts/sysvars.rs b/test-utils/src/accounts/sysvars.rs index 806e254b..8e5bfd37 100644 --- a/test-utils/src/accounts/sysvars.rs +++ b/test-utils/src/accounts/sysvars.rs @@ -1,9 +1,100 @@ +use generic_array_struct::generic_array_struct; use jiminy_sysvar_instructions::sysvar::OWNER_ID; use solana_account::Account; +use solana_clock::Clock; use solana_instruction::{BorrowedAccountMeta, BorrowedInstruction, Instruction}; use solana_instructions_sysvar::construct_instructions_data; use solana_pubkey::Pubkey; +#[generic_array_struct(builder pub)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ClockI64s { + pub epoch_start_timestamp: T, + pub unix_timestamp: T, +} + +impl<'a> ClockI64s<&'a mut i64> { + pub fn muts( + Clock { + epoch_start_timestamp, + unix_timestamp, + .. + }: &'a mut Clock, + ) -> Self { + NewClockI64sBuilder::start() + .with_epoch_start_timestamp(epoch_start_timestamp) + .with_unix_timestamp(unix_timestamp) + .build() + } +} + +#[generic_array_struct(builder pub)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ClockU64s { + pub slot: T, + pub epoch: T, + pub leader_schedule_epoch: T, +} + +impl<'a> ClockU64s<&'a mut u64> { + pub fn muts( + Clock { + slot, + epoch, + leader_schedule_epoch, + .. + }: &'a mut Clock, + ) -> Self { + NewClockU64sBuilder::start() + .with_slot(slot) + .with_epoch(epoch) + .with_leader_schedule_epoch(leader_schedule_epoch) + .build() + } +} + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ClockArgs { + pub i64s: ClockI64s, + pub u64s: ClockU64s, +} + +impl From> for Clock { + fn from(ClockArgs { u64s, i64s }: ClockArgs) -> Self { + Self { + slot: *u64s.slot(), + epoch_start_timestamp: *i64s.epoch_start_timestamp(), + epoch: *u64s.epoch(), + leader_schedule_epoch: *u64s.leader_schedule_epoch(), + unix_timestamp: *i64s.unix_timestamp(), + } + } +} + +pub fn override_clock( + clock: &mut Clock, + ClockArgs { i64s, u64s }: &ClockArgs, Option>, +) { + ClockI64s::muts(clock) + .0 + .into_iter() + .zip(i64s.0) + .for_each(|(r, v)| { + if let Some(v) = v { + *r = v; + } + }); + ClockU64s::muts(clock) + .0 + .into_iter() + .zip(u64s.0) + .for_each(|(r, v)| { + if let Some(v) = v { + *r = v; + } + }); +} + /// Clock with everything = 0 pub fn mock_clock() -> Account { Account { diff --git a/test-utils/src/gen/common.rs b/test-utils/src/gen/common.rs index 87a7ddb4..e9a8669a 100644 --- a/test-utils/src/gen/common.rs +++ b/test-utils/src/gen/common.rs @@ -1,5 +1,7 @@ use proptest::prelude::*; +use crate::any_normal_pk; + macro_rules! int_strat { ($f:ident, $I:ty) => { pub fn $f(ovride: Option>) -> BoxedStrategy<$I> { @@ -19,7 +21,7 @@ pub fn bool_strat(ovride: Option>) -> BoxedStrategy { } pub fn pk_strat(ovrride: Option>) -> BoxedStrategy<[u8; 32]> { - ovrride.unwrap_or_else(|| any::<[u8; 32]>().boxed()) + ovrride.unwrap_or_else(|| any_normal_pk().boxed()) } /// Converts a `Option` to `Strategy