diff --git a/modules/homa-lite/src/lib.rs b/modules/homa-lite/src/lib.rs index c21e2e9afb..d4a221355b 100644 --- a/modules/homa-lite/src/lib.rs +++ b/modules/homa-lite/src/lib.rs @@ -59,6 +59,12 @@ pub mod module { pub(crate) type AmountOf = <::Currency as MultiCurrencyExtended<::AccountId>>::Amount; + #[derive(Debug, Clone, Copy, PartialEq)] + pub enum RedeemType { + WithAvailableStakingBalance, + WithMint(AccountId, Balance), + } + #[pallet::config] pub trait Config: frame_system::Config + pallet_xcm::Config { type Event: From> + IsType<::Event>; @@ -261,10 +267,10 @@ pub mod module { pub type StakingInterestRatePerUpdate = StorageValue<_, Permill, ValueQuery>; /// Next redeem request to iterate from when matching redeem requests. - /// RedeemRequestKeyToIterFrom: Value: T::AccountId + /// LastRedeemRequestKeyIterated: Value: T::AccountId #[pallet::storage] - #[pallet::getter(fn redeem_request_key_to_iter_from)] - pub type RedeemRequestKeyToIterFrom = StorageValue<_, Vec, ValueQuery>; + #[pallet::getter(fn last_redeem_request_key_iterated)] + pub type LastRedeemRequestKeyIterated = StorageValue<_, Vec, ValueQuery>; #[pallet::pallet] pub struct Pallet(_); @@ -300,9 +306,12 @@ pub mod module { .unwrap_or_default(); // Iterate through existing redeem_requests, and try to match them with `available_staking_balance` - let res = Self::process_redeem_requests_with_available_staking_balance(num_redeem_matches as u32); + let res = Self::redeem_from_previous_redeem_request( + RedeemType::WithAvailableStakingBalance, + num_redeem_matches as u32, + ); debug_assert!(res.is_ok()); - if let Ok(count) = res { + if let Ok((_, count)) = res { current_weight = current_weight.saturating_add( ::WeightInfo::redeem_with_available_staking_balance().saturating_mul(count as Weight), ); @@ -533,7 +542,7 @@ pub mod module { })?; // With redeem request added to the queue, try to redeem it with available staking balance. - Self::process_redeem_requests_with_available_staking_balance(1)?; + Self::process_redeem_requests_with_available_staking_balance(who)?; Ok(()) } @@ -635,7 +644,7 @@ pub mod module { }); // With new staking balance available, process pending redeem requests. - Self::process_redeem_requests_with_available_staking_balance(max_num_matches)?; + Self::redeem_from_previous_redeem_request(RedeemType::WithAvailableStakingBalance, max_num_matches)?; Ok(()) } @@ -691,7 +700,7 @@ pub mod module { /// Param: /// - `minter`: The AccountId requested the Mint /// - `redeemer`: The AccountId requested the Redeem - /// - `liquid_amount_remaining`: The amount of liquid currency still remain to be minted. + /// - `liquid_amount_to_redeem`: The amount of liquid currency still remain to be minted. /// Only redeem up to this amount. /// /// Return: @@ -699,7 +708,7 @@ pub mod module { fn match_mint_with_redeem_request( minter: &T::AccountId, redeemer: &T::AccountId, - liquid_amount_remaining: Balance, + liquid_amount_to_redeem: Balance, ) -> Result { RedeemRequests::::mutate_exists(&redeemer, |request| { let (request_amount, extra_fee) = request.unwrap_or_default(); @@ -708,7 +717,7 @@ pub mod module { return Ok(0); } - let actual_liquid_amount = min(request_amount, liquid_amount_remaining); + let actual_liquid_amount = min(request_amount, liquid_amount_to_redeem); // Ensure the redeemer have enough liquid currency in their account. if T::Currency::reserved_balance(T::LiquidCurrencyId::get(), redeemer) < actual_liquid_amount { @@ -800,29 +809,14 @@ pub mod module { } } - let mut redeem_requests_limit_remaining = T::MaximumRedeemRequestMatchesForMint::get(); + // Iterate through the rest of the RedeemRequests to mint + let redeem_requests_limit_remaining = T::MaximumRedeemRequestMatchesForMint::get(); if !liquid_remaining.is_zero() && !redeem_requests_limit_remaining.is_zero() { - // Define the function to be executed for each of the redeem request: - // Redeem the given requests with the current minting request. - // - // Params: redeemer: T::AccountId - // Returns: Result - // - // Capturing: &mut liquid_remaining - // &mut redeem_requests_limit_remaining - // If all the currencies are minted, return `should_break` as true. - let mut f = |redeemer| -> Result { - let actual_liquid_redeemed = - Self::match_mint_with_redeem_request(minter, &redeemer, liquid_remaining)?; - liquid_remaining = liquid_remaining.saturating_sub(actual_liquid_redeemed); - redeem_requests_limit_remaining -= 1; - - // Should break when all currencies are minted - Ok(liquid_remaining.is_zero() || redeem_requests_limit_remaining.is_zero()) - }; - - // Call the function on redeem requests - iterating from the `RedeemRequestKeyToIterFrom` - Self::iterate_from_next_redeem_request(&mut f)?; + let (liquid_amount_redeemed, _) = Self::redeem_from_previous_redeem_request( + RedeemType::WithMint(minter.clone(), liquid_remaining), + redeem_requests_limit_remaining, + )?; + liquid_remaining = liquid_remaining.saturating_sub(liquid_amount_redeemed); } // If significant balance is left over, the remaining liquid currencies are minted through XCM. @@ -892,101 +886,75 @@ pub mod module { Ok(()) } - /// Iterate through all redeem requests, then match them with available_staking_balance. - /// This should be called when new available_staking_balance becomes available. + /// Redeem the given requests with available_staking_balance. /// /// params: - /// - `max_num_matches`: Maximum number of redeem requests to be matched. + /// - `redeemer`: The account Id of the redeem requester /// /// return: - /// Result: The number of redeem requests actually matched. + /// -`Result`: The liquid amount actually redeemed. #[transactional] pub fn process_redeem_requests_with_available_staking_balance( - max_num_matches: u32, - ) -> Result { - if max_num_matches.is_zero() { - return Ok(0); - } - let mut available_staking_balance = Self::available_staking_balance(); + redeemer: T::AccountId, + ) -> Result { + let available_staking_balance = Self::available_staking_balance(); if available_staking_balance <= T::MinimumMintThreshold::get() { return Ok(0); } - let mut num_matched = 0u32; + RedeemRequests::::mutate_exists(&redeemer, |request| { + let (request_amount, extra_fee) = request.unwrap_or_default(); + // If the redeem request doesn't exist, return. + if request_amount.is_zero() { + return Ok(0); + } - { - // Define the function to be executed for each of the redeem request: - // Redeem the given requests using available_staking_balance. - // - // Params: redeemer: T::AccountId - // Returns: Result - let mut f = |redeemer| -> Result { - RedeemRequests::::mutate_exists(&redeemer, |request| { - let (request_amount, extra_fee) = request.unwrap_or_default(); - // If the redeem request doesn't exist, return. - if request_amount.is_zero() { - return Ok(false); - } + let actual_liquid_amount = min( + request_amount, + Self::convert_staking_to_liquid(available_staking_balance)?, + ); - let actual_liquid_amount = min( - request_amount, - Self::convert_staking_to_liquid(available_staking_balance)?, - ); + // Ensure the redeemer have enough liquid currency in their account. + if T::Currency::reserved_balance(T::LiquidCurrencyId::get(), &redeemer) < actual_liquid_amount { + return Ok(0); + } + let actual_staking_amount = Self::convert_liquid_to_staking(actual_liquid_amount)?; - // Ensure the redeemer have enough liquid currency in their account. - if T::Currency::reserved_balance(T::LiquidCurrencyId::get(), &redeemer) < actual_liquid_amount { - return Ok(false); - } - let actual_staking_amount = Self::convert_liquid_to_staking(actual_liquid_amount)?; - - Self::update_total_staking_currency_storage(|total| { - Ok(total.saturating_sub(actual_staking_amount)) - })?; - - //Actual deposit amount has `T::XcmUnbondFee` deducted. - let actual_staking_amount_deposited = - actual_staking_amount.saturating_sub(T::XcmUnbondFee::get()); - T::Currency::deposit(T::StakingCurrencyId::get(), &redeemer, actual_staking_amount_deposited)?; - - // Burn the corresponding amount of Liquid currency from the user. - // The redeemer is guaranteed to have enough fund - T::Currency::unreserve(T::LiquidCurrencyId::get(), &redeemer, actual_liquid_amount); - T::Currency::slash(T::LiquidCurrencyId::get(), &redeemer, actual_liquid_amount); - - available_staking_balance = available_staking_balance.saturating_sub(actual_staking_amount); - - Self::deposit_event(Event::::Redeemed( - redeemer.clone(), - actual_staking_amount_deposited, - actual_liquid_amount, - )); - num_matched += 1u32; - - // Update storage - let new_amount = request_amount.saturating_sub(actual_liquid_amount); - if Self::liquid_amount_is_above_minimum_threshold(new_amount) { - *request = Some((new_amount, extra_fee)); - } else { - // Unlock the dust and remove the request. - if !new_amount.is_zero() { - T::Currency::unreserve(T::LiquidCurrencyId::get(), &redeemer, new_amount); - } - *request = None; - } + Self::update_total_staking_currency_storage(|total| Ok(total.saturating_sub(actual_staking_amount)))?; - // If all the currencies are minted, return `should_break` as true - Ok(available_staking_balance <= T::MinimumMintThreshold::get() - || num_matched >= max_num_matches) - }) - }; + //Actual deposit amount has `T::XcmUnbondFee` deducted. + let actual_staking_amount_deposited = actual_staking_amount.saturating_sub(T::XcmUnbondFee::get()); + T::Currency::deposit(T::StakingCurrencyId::get(), &redeemer, actual_staking_amount_deposited)?; - // Redeem requests from `RedeemRequestKeyToIterFrom` using available_staking_balance. - Self::iterate_from_next_redeem_request(&mut f)?; - } + // Burn the corresponding amount of Liquid currency from the user. + // The redeemer is guaranteed to have enough fund + T::Currency::unreserve(T::LiquidCurrencyId::get(), &redeemer, actual_liquid_amount); + T::Currency::slash(T::LiquidCurrencyId::get(), &redeemer, actual_liquid_amount); + + AvailableStakingBalance::::mutate(|current| { + *current = current.saturating_sub(actual_staking_amount) + }); + + Self::deposit_event(Event::::Redeemed( + redeemer.clone(), + actual_staking_amount_deposited, + actual_liquid_amount, + )); - AvailableStakingBalance::::put(available_staking_balance); + // Update storage + let new_amount = request_amount.saturating_sub(actual_liquid_amount); + if Self::liquid_amount_is_above_minimum_threshold(new_amount) { + *request = Some((new_amount, extra_fee)); + } else { + // Unlock the dust and remove the request. + if !new_amount.is_zero() { + T::Currency::unreserve(T::LiquidCurrencyId::get(), &redeemer, new_amount); + } + *request = None; + } - Ok(num_matched) + Ok(actual_liquid_amount) + }) } // Helper function that checks if the `liquid_amount` is above the minimum redeem threshold, and @@ -1033,24 +1001,26 @@ pub mod module { }) } - /// Helper function that iterates `RedeemRequests` storage from - /// `RedeemRequestKeyToIterFrom`, and call the MutFn f() on that request - /// - /// At the end of iteration, `RedeemRequests` storage is culled. - /// - /// If the item after `RedeemRequestKeyToIterFrom` is the end of the iterator, then start + /// Function that iterates `RedeemRequests` storage from `LastRedeemRequestKeyIterated`, and + /// redeem them depending on the redeem type. Either redeem from AvailableStakingBalance, or + /// from a specific minter. + /// If the item after `LastRedeemRequestKeyIterated` is the end of the iterator, then start /// from the beginning. /// /// Param: - /// - FnMut f: - /// Param: `redeemer`: AccountId of the redeemer - /// Return: Result: if the iteration should break. - pub fn iterate_from_next_redeem_request( - f: &mut impl FnMut(T::AccountId) -> Result, - ) -> DispatchResult { + /// - `redeem_type`: How redeem should happen. + /// - `max_num_matches`: Maximum number of requests to be redeemed. + /// + /// Return: + /// - `total_amount_redeemed`: the total amount of liquid actually redeemed + /// - `num_matched`: number of requests actually redeemed. + pub fn redeem_from_previous_redeem_request( + redeem_type: RedeemType, + max_num_matches: u32, + ) -> Result<(Balance, u32), DispatchError> { // If "next" after starting key exists in storage, use it as the "starting_item". Otherwise use the // first item. - let starting_key = Self::redeem_request_key_to_iter_from(); + let starting_key = Self::last_redeem_request_key_iterated(); let (mut iterator, starting_element) = match RedeemRequests::::iter_from(starting_key.clone()).next() { Some(request) => { // reset the iterator @@ -1060,39 +1030,88 @@ pub mod module { // iterate from the start match RedeemRequests::::iter().next() { // Current storage is empty. Do nothing and return - None => return Ok(()), + None => return Ok((0, 0)), Some(element) => (RedeemRequests::::iter(), element), } } }; - // Iterate until the end of the storage, calling f() for each element - #[allow(clippy::while_let_on_iterator)] - while let Some((redeemer, _)) = iterator.next() { - if f(redeemer.clone())? { - // Store the `current` element as `RedeemRequestKeyToIterFrom` - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for(redeemer)); - return Ok(()); - } - } + let mut redeem_amount_remaining = if let RedeemType::WithMint(_, amount) = redeem_type { + amount + } else { + 0 + }; - // Reset the iterator and start from the beginning of the storage until `starting_redeemer`, calling - // f() for each element. - iterator = RedeemRequests::::iter(); + let mut total_amount_redeemed: Balance = 0; + let mut num_matched = 0u32; + let mut finished_iteration = false; #[allow(clippy::while_let_on_iterator)] while let Some((redeemer, _)) = iterator.next() { - if redeemer == starting_element.0 { - // We have wrapped to the beginning. Stop the loop. + if num_matched >= max_num_matches { + finished_iteration = true; break; } - if f(redeemer.clone())? { - // Store the `current` element as `RedeemRequestKeyToIterFrom` - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for(redeemer)); - break; + num_matched += 1; + match redeem_type.clone() { + RedeemType::WithAvailableStakingBalance => { + let amount_redeemed = + Self::process_redeem_requests_with_available_staking_balance(redeemer.clone())?; + total_amount_redeemed = total_amount_redeemed.saturating_add(amount_redeemed); + if Self::available_staking_balance() <= T::MinimumMintThreshold::get() { + finished_iteration = true; + break; + } + } + RedeemType::WithMint(minter, _) => { + let amount_redeemed = + Self::match_mint_with_redeem_request(&minter, &redeemer, redeem_amount_remaining)?; + total_amount_redeemed = total_amount_redeemed.saturating_add(amount_redeemed); + redeem_amount_remaining = redeem_amount_remaining.saturating_sub(amount_redeemed); + if !Self::liquid_amount_is_above_minimum_threshold(redeem_amount_remaining) { + finished_iteration = true; + break; + } + } } } - Ok(()) + + if !finished_iteration { + // Reset the iterator and start from the beginning of the storage until `starting_redeemer`, calling + // f() for each element. + iterator = RedeemRequests::::iter(); + + #[allow(clippy::while_let_on_iterator)] + while let Some((redeemer, _)) = iterator.next() { + if redeemer == starting_element.0 || num_matched >= max_num_matches { + break; + } + num_matched += 1; + match redeem_type.clone() { + RedeemType::WithAvailableStakingBalance => { + let amount_redeemed = + Self::process_redeem_requests_with_available_staking_balance(redeemer.clone())?; + total_amount_redeemed = total_amount_redeemed.saturating_add(amount_redeemed); + if Self::available_staking_balance() <= T::MinimumMintThreshold::get() { + break; + } + } + RedeemType::WithMint(minter, _) => { + let amount_redeemed = + Self::match_mint_with_redeem_request(&minter, &redeemer, redeem_amount_remaining)?; + total_amount_redeemed = total_amount_redeemed.saturating_add(amount_redeemed); + redeem_amount_remaining = redeem_amount_remaining.saturating_sub(amount_redeemed); + if !Self::liquid_amount_is_above_minimum_threshold(redeem_amount_remaining) { + break; + } + } + } + } + } + + // Store the progress of the iterator + LastRedeemRequestKeyIterated::::put(iterator.last_raw_key()); + Ok((total_amount_redeemed, num_matched)) } } diff --git a/modules/homa-lite/src/tests.rs b/modules/homa-lite/src/tests.rs index e8288348f8..e5fba2ffc0 100644 --- a/modules/homa-lite/src/tests.rs +++ b/modules/homa-lite/src/tests.rs @@ -1640,9 +1640,9 @@ fn adjust_available_staking_balance_matches_redeem_based_on_input() { RedeemRequests::::get(DAVE), Some((dollar(999), Permill::zero())) ); - assert_eq!(RedeemRequests::::get(ALICE), None); + assert_eq!(RedeemRequests::::get(BOB), None); assert_eq!( - RedeemRequests::::get(BOB), + RedeemRequests::::get(ALICE), Some((dollar(999), Permill::zero())) ); diff --git a/modules/homa-lite/src/tests_no_fees.rs b/modules/homa-lite/src/tests_no_fees.rs index daafe14cd4..f799871953 100644 --- a/modules/homa-lite/src/tests_no_fees.rs +++ b/modules/homa-lite/src/tests_no_fees.rs @@ -343,309 +343,7 @@ fn updating_and_cancelling_redeem_requests_does_not_change_exchange_rate() { } #[test] -fn iterate_redeem_requests_from_next_works() { - ExtBuilder::empty().build().execute_with(|| { - // iterate works with empty redeem requests - let mut empty: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([0; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &empty.push(redeemer); - Ok(false) - } - )); - } - assert_eq!(empty, vec![]); - - // iterate works with 1 redeem request - { - let account = AccountId::from([1u8; 32]); - assert_ok!(Currencies::update_balance( - Origin::root(), - account.clone(), - LKSM, - dollar(1) as i128 - )); - assert_ok!(HomaLite::request_redeem( - Origin::signed(account), - dollar(1), - Permill::zero() - )); - } - - let mut one_request: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([0; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &one_request.push(redeemer); - Ok(false) - } - )); - } - assert_eq!(one_request, vec![AccountId::from([1u8; 32])]); - - let mut one_request_2: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([1; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &one_request_2.push(redeemer); - Ok(false) - } - )); - } - assert_eq!(one_request_2, vec![AccountId::from([1u8; 32])]); - - // iterate works with 2 redeem requests - { - let account = AccountId::from([2u8; 32]); - assert_ok!(Currencies::update_balance( - Origin::root(), - account.clone(), - LKSM, - dollar(2) as i128 - )); - assert_ok!(HomaLite::request_redeem( - Origin::signed(account), - dollar(2), - Permill::zero() - )); - } - - let mut two_requests_1: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([0; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &two_requests_1.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - two_requests_1, - vec![AccountId::from([1u8; 32]), AccountId::from([2u8; 32])] - ); - - let mut two_requests_2: Vec = vec![]; - // Iterate from 1: next item is 2 - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([1; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &two_requests_2.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - two_requests_2, - vec![AccountId::from([2u8; 32]), AccountId::from([1u8; 32])] - ); - - let mut two_requests_3: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([2; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &two_requests_3.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - two_requests_3, - vec![AccountId::from([1u8; 32]), AccountId::from([2u8; 32])] - ); - - // Test with larger number of requests in storage - for i in 3u8..10u8 { - let account = AccountId::from([i; 32]); - assert_ok!(Currencies::update_balance( - Origin::root(), - account.clone(), - LKSM, - dollar(i as u128) as i128 - )); - assert_ok!(HomaLite::request_redeem( - Origin::signed(account), - dollar(i as u128), - Permill::zero() - )); - } - - // This is the default order the redeem requests are iterated. - let mut default_order = vec![]; - for (redeemer, _) in RedeemRequests::::iter() { - default_order.push(redeemer); - } - assert_eq!( - default_order, - vec![ - AccountId::from([1u8; 32]), - AccountId::from([6u8; 32]), - AccountId::from([2u8; 32]), - AccountId::from([3u8; 32]), - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]), - AccountId::from([4u8; 32]), - AccountId::from([5u8; 32]) - ] - ); - - // iterate from the middle - let mut output_1: Vec = vec![]; - // Set iter_from key to 3, so iteration starts from 8 - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([3; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &output_1.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - output_1, - vec![ - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]), - AccountId::from([4u8; 32]), - AccountId::from([5u8; 32]), - AccountId::from([1u8; 32]), - AccountId::from([6u8; 32]), - AccountId::from([2u8; 32]), - AccountId::from([3u8; 32]), - ] - ); - - // Iterate from the start - let mut output_2: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([5; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &output_2.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - output_2, - vec![ - AccountId::from([1u8; 32]), - AccountId::from([6u8; 32]), - AccountId::from([2u8; 32]), - AccountId::from([3u8; 32]), - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]), - AccountId::from([4u8; 32]), - AccountId::from([5u8; 32]), - ] - ); - - // Iterate from the end - let mut output_3: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([4; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &output_3.push(redeemer); - Ok(false) - } - )); - } - assert_eq!( - output_3, - vec![ - AccountId::from([5u8; 32]), - AccountId::from([1u8; 32]), - AccountId::from([6u8; 32]), - AccountId::from([2u8; 32]), - AccountId::from([3u8; 32]), - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]), - AccountId::from([4u8; 32]), - ] - ); - - // If breaking half way through, return immediately. - let mut output_5: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([3; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &output_5.push(redeemer.clone()); - Ok(redeemer == AccountId::from([7u8; 32])) - } - )); - } - assert_eq!( - output_5, - vec![ - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]) - ] - ); - - // If breaking half way through, return immediately. - let mut output_6: Vec = vec![]; - RedeemRequestKeyToIterFrom::::put(RedeemRequests::::hashed_key_for( - AccountId::from([3; 32]), - )); - { - assert_ok!(HomaLite::iterate_from_next_redeem_request( - &mut |redeemer: AccountId| -> Result { - &output_6.push(redeemer.clone()); - Ok(redeemer == AccountId::from([2u8; 32])) - } - )); - } - assert_eq!( - output_6, - vec![ - AccountId::from([8u8; 32]), - AccountId::from([9u8; 32]), - AccountId::from([7u8; 32]), - AccountId::from([4u8; 32]), - AccountId::from([5u8; 32]), - AccountId::from([1u8; 32]), - AccountId::from([6u8; 32]), - AccountId::from([2u8; 32]), - ] - ); - }); -} - -#[test] -fn mint_match_from_next_redeem_requests() { +fn mint_match_from_previous_redeem_requests() { ExtBuilder::empty().build().execute_with(|| { assert_ok!(HomaLite::set_minting_cap(Origin::root(), dollar(1_000_000))); @@ -698,8 +396,8 @@ fn mint_match_from_next_redeem_requests() { dollar(100 as u128) as i128 )); - // If unset, `RedeemRequestKeyToIterFrom` should be the default account Id - assert!(HomaLite::redeem_request_key_to_iter_from().is_empty()); + // If unset, `LastRedeemRequestKeyIterated` should be the default account Id + assert!(HomaLite::last_redeem_request_key_iterated().is_empty()); // Minting once for each item in redeem request should be iterated once for i in 0..10 { @@ -710,9 +408,9 @@ fn mint_match_from_next_redeem_requests() { Some((dollar(900), Permill::zero())) ); assert_eq!(Currencies::free_balance(KSM, &default_order[i]), dollar(10)); - // Ensure `RedeemRequestKeyToIterFrom` is setup correctly. + // Ensure `LastRedeemRequestKeyIterated` is setup correctly. assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(default_order[i].clone()) ); } @@ -751,7 +449,7 @@ fn mint_match_from_next_redeem_requests() { } #[test] -fn unbonded_staking_match_from_next_redeem_requests() { +fn unbonded_staking_match_from_previous_redeem_requests() { let mut unbond = |amount: Balance| -> DispatchResult { assert_ok!(HomaLite::schedule_unbond(Origin::root(), amount, 0)); HomaLite::on_idle(0, 5_000_000_000); @@ -762,17 +460,19 @@ fn unbonded_staking_match_from_next_redeem_requests() { HomaLite::adjust_available_staking_balance(Origin::root(), amount as i128, 1_000) }; - // Test unbonding can iterate from `RedeemRequestKeyToIterFrom` - test_increase_staking_match_from_next_redeem_requests(&mut unbond); + // Test unbonding can iterate from `LastRedeemRequestKeyIterated` + test_increase_staking_match_from_previous_redeem_requests(&mut unbond); - // Test `adjust_available_staking_balance` can iterate from `RedeemRequestKeyToIterFrom` - test_increase_staking_match_from_next_redeem_requests(&mut adjust_available_staking_balance); + // Test `adjust_available_staking_balance` can iterate from `LastRedeemRequestKeyIterated` + test_increase_staking_match_from_previous_redeem_requests(&mut adjust_available_staking_balance); } // Helper function that tests when increasing Staking currency, the redeem requests are processed -// from the `RedeemRequestKeyToIterFrom`. Takes a Function that increases the StakingCurrency and +// from the `LastRedeemRequestKeyIterated`. Takes a Function that increases the StakingCurrency and // matches redeem requests. -fn test_increase_staking_match_from_next_redeem_requests(mut increase_staking: impl FnMut(Balance) -> DispatchResult) { +fn test_increase_staking_match_from_previous_redeem_requests( + mut increase_staking: impl FnMut(Balance) -> DispatchResult, +) { ExtBuilder::empty().build().execute_with(|| { assert_ok!(HomaLite::set_minting_cap(Origin::root(), dollar(1_000_000))); @@ -825,8 +525,8 @@ fn test_increase_staking_match_from_next_redeem_requests(mut increase_staking: i ] ); - // If unset, `RedeemRequestKeyToIterFrom` should be the default account Id - assert!(HomaLite::redeem_request_key_to_iter_from().is_empty()); + // If unset, `LastRedeemRequestKeyIterated` should be the default account Id + assert!(HomaLite::last_redeem_request_key_iterated().is_empty()); assert_eq!(HomaLite::total_staking_currency(), dollar(1001)); @@ -840,16 +540,16 @@ fn test_increase_staking_match_from_next_redeem_requests(mut increase_staking: i Some((dollar(900), Permill::zero())) ); assert_eq!(Currencies::free_balance(KSM, &default_order[i]), dollar(10)); - // Ensure `RedeemRequestKeyToIterFrom` is setup correctly. + // Ensure `LastRedeemRequestKeyIterated` is setup correctly. assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(default_order[i].clone()) ); } - // Ensure `RedeemRequestKeyToIterFrom` is setup correctly. + // Ensure `LastRedeemRequestKeyIterated` is setup correctly. assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(AccountId::default().clone()) ); @@ -873,7 +573,7 @@ fn test_increase_staking_match_from_next_redeem_requests(mut increase_staking: i } #[test] -fn redeem_doesn_not_restart_if_next_key_is_removed() { +fn redeem_does_not_restart_if_previous_key_is_removed() { ExtBuilder::empty().build().execute_with(|| { assert_ok!(HomaLite::set_minting_cap(Origin::root(), dollar(1_000_000))); @@ -930,7 +630,7 @@ fn redeem_doesn_not_restart_if_next_key_is_removed() { assert_eq!(Currencies::free_balance(KSM, &AccountId::from([1u8; 32])), dollar(10)); assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(AccountId::from([1u8; 32])) ); @@ -947,7 +647,7 @@ fn redeem_doesn_not_restart_if_next_key_is_removed() { assert_eq!(Currencies::free_balance(KSM, &AccountId::from([3u8; 32])), dollar(10)); assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(AccountId::from([3u8; 32])) ); @@ -964,7 +664,7 @@ fn redeem_doesn_not_restart_if_next_key_is_removed() { assert_eq!(Currencies::free_balance(KSM, &AccountId::from([1u8; 32])), dollar(20)); assert_eq!( - HomaLite::redeem_request_key_to_iter_from(), + HomaLite::last_redeem_request_key_iterated(), RedeemRequests::::hashed_key_for(AccountId::from([1u8; 32])) ); });