From 621f7b80bd5c9ecd9bf8103b068398aa840bf7f1 Mon Sep 17 00:00:00 2001 From: mrq Date: Tue, 16 Jul 2024 15:27:55 +0200 Subject: [PATCH 01/17] scheduling checks --- pallets/dca/src/lib.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index f0504baea..fb23d0f97 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -85,6 +85,7 @@ use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; +use scale_info::TypeDefPrimitive::U256; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; use sp_runtime::traits::{CheckedMul, One}; use sp_runtime::{ @@ -368,6 +369,10 @@ pub mod pallet { NoParentHashFound, ///Error that should not really happen only in case of invalid state of the schedule storage entries InvalidState, + ///Period should be longer than 5 blocks + PeriodTooShort, + ///Stability threshold cannot be higher than 5% + StabilityThresholdTooHigh, } /// Id sequencer for schedules @@ -449,6 +454,17 @@ pub mod pallet { schedule.total_amount >= min_budget, Error::::TotalAmountIsSmallerThanMinBudget ); + ensure!( + schedule.period >= BlockNumberFor::::from(5u32), + Error::::PeriodTooShort + ); + ensure!( + match schedule.stability_threshold { + Some(threshold) => threshold <= Permill::from_percent(5), + None => true, + }, + Error::::StabilityThresholdTooHigh + ); let transaction_fee = Self::get_transaction_fee(&schedule.order)?; @@ -469,9 +485,7 @@ pub mod pallet { Error::::MinTradeAmountNotReached ); - let amount_in_with_transaction_fee = amount_in - .checked_add(transaction_fee) - .ok_or(ArithmeticError::Overflow)?; + let amount_in_with_transaction_fee = amount_in.saturating_add(transaction_fee).saturating_mul(2); ensure!( amount_in_with_transaction_fee <= schedule.total_amount, Error::::BudgetTooLow @@ -600,11 +614,15 @@ impl Pallet { start_execution_block: Option>, ) -> Result, DispatchError> { let blocknumber_for_first_schedule_execution = match start_execution_block { - Some(blocknumber) => Ok(blocknumber), + Some(blocknumber) => { + let remainder: u32 = (blocknumber.into() % 5).as_u32(); + let diff = if remainder == 0 { 0 } else { 5u32 - remainder }; + Ok(blocknumber.saturating_add(BlockNumberFor::::from(diff))) + } None => { let current_block_number = frame_system::Pallet::::current_block_number(); let next_block_number = current_block_number - .checked_add(&BlockNumberFor::::one()) + .checked_add(&BlockNumberFor::::from(2u32)) .ok_or(ArithmeticError::Overflow)?; Ok::, ArithmeticError>(next_block_number) From 826862b3b9a32042fbaf98e12fe10f9473c0c785 Mon Sep 17 00:00:00 2001 From: mrq Date: Tue, 16 Jul 2024 15:40:09 +0200 Subject: [PATCH 02/17] clearer error desc --- pallets/dca/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index fb23d0f97..d6d2aaf3e 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -85,7 +85,6 @@ use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; -use scale_info::TypeDefPrimitive::U256; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; use sp_runtime::traits::{CheckedMul, One}; use sp_runtime::{ @@ -353,7 +352,7 @@ pub mod pallet { CalculatingPriceError, ///The total amount to be reserved is smaller than min budget TotalAmountIsSmallerThanMinBudget, - ///The budget is too low for executing one DCA + ///The budget is too low for executing at least two orders BudgetTooLow, ///There is no free block found to plan DCA execution NoFreeBlockFound, From 3611d1dfc884ec5e12c30d4c2f08b59b65f138c1 Mon Sep 17 00:00:00 2001 From: mrq Date: Tue, 16 Jul 2024 15:42:19 +0200 Subject: [PATCH 03/17] typo --- pallets/dca/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index d6d2aaf3e..38610ee50 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -360,7 +360,7 @@ pub mod pallet { ManuallyTerminated, ///Max number of retries reached for schedule MaxRetryReached, - ///Absolutely trade limit reached reached, leading to retry + ///Absolutely trade limit reached, leading to retry TradeLimitReached, ///Slippage limit calculated from oracle is reached, leading to retry SlippageLimitReached, From d5de7dd7d04a37cb578a5a9a6562178e7468bd80 Mon Sep 17 00:00:00 2001 From: mrq Date: Wed, 17 Jul 2024 15:30:27 +0200 Subject: [PATCH 04/17] random bump added resolved PR suggestions --- pallets/dca/src/lib.rs | 46 ++++++++++++++++++++++++++--------- pallets/dca/src/tests/mock.rs | 8 +++++- runtime/hydradx/src/assets.rs | 8 +++++- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index 38610ee50..cb9e04d33 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -86,10 +86,10 @@ use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCur use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; -use sp_runtime::traits::{CheckedMul, One}; +use sp_runtime::traits::CheckedMul; use sp_runtime::{ traits::{BlockNumberProvider, Saturating}, - ArithmeticError, BoundedVec, DispatchError, FixedPointNumber, FixedU128, Permill, Rounding, + ArithmeticError, BoundedVec, DispatchError, FixedPointNumber, FixedU128, Percent, Permill, Rounding, }; use sp_std::vec::Vec; @@ -123,6 +123,7 @@ pub mod pallet { use hydra_dx_math::ema::EmaPrice; use hydradx_traits::{NativePriceOracle, PriceOracle}; use orml_traits::NamedMultiReservableCurrency; + use sp_runtime::Percent; #[pallet::pallet] pub struct Pallet(_); @@ -158,10 +159,11 @@ pub mod pallet { &schedule, &mut randomness_generator, ) { - if e != Error::::PriceUnstable.into() { + if e == Error::::PriceUnstable.into() || e == Error::::Bumped.into() { + continue; + } else { Self::terminate_schedule(schedule_id, &schedule, e); - }; - continue; + } }; match Self::execute_trade(schedule_id, &schedule) { @@ -251,6 +253,10 @@ pub mod pallet { #[pallet::constant] type MaxPriceDifferenceBetweenBlocks: Get; + ///Max configurable price difference allowed between blocks + #[pallet::constant] + type MaxConfigurablePriceDifferenceBetweenBlocks: Get; + ///The number of max schedules to be executed per block #[pallet::constant] type MaxSchedulePerBlock: Get; @@ -259,6 +265,14 @@ pub mod pallet { #[pallet::constant] type MaxNumberOfRetriesOnError: Get; + ///Minimal period between executions + #[pallet::constant] + type MinimalPeriod: Get; + + ///Chance of the random rescheduling + #[pallet::constant] + type BumpChance: Get; + /// Minimum trading limit for a single trade #[pallet::constant] type MinimumTradingLimit: Get; @@ -348,6 +362,8 @@ pub mod pallet { BlockNumberIsNotInFuture, ///Price is unstable as price change from oracle data is bigger than max allowed PriceUnstable, + ///Order was randomly rescheduled to next block + Bumped, ///Error occurred when calculating price CalculatingPriceError, ///The total amount to be reserved is smaller than min budget @@ -370,7 +386,7 @@ pub mod pallet { InvalidState, ///Period should be longer than 5 blocks PeriodTooShort, - ///Stability threshold cannot be higher than 5% + ///Stability threshold cannot be higher than `MaxConfigurablePriceDifferenceBetweenBlock` StabilityThresholdTooHigh, } @@ -429,7 +445,7 @@ pub mod pallet { /// Parameters: /// - `origin`: schedule owner /// - `schedule`: schedule details - /// - `start_execution_block`: start execution block for the schedule + /// - `start_execution_block`: first possible execution block for the schedule /// /// Emits `Scheduled` and `ExecutionPlanned` event when successful. /// @@ -454,12 +470,12 @@ pub mod pallet { Error::::TotalAmountIsSmallerThanMinBudget ); ensure!( - schedule.period >= BlockNumberFor::::from(5u32), + schedule.period >= BlockNumberFor::::from(T::MinimalPeriod::get()), Error::::PeriodTooShort ); ensure!( match schedule.stability_threshold { - Some(threshold) => threshold <= Permill::from_percent(5), + Some(threshold) => threshold <= T::MaxConfigurablePriceDifferenceBetweenBlocks::get(), None => true, }, Error::::StabilityThresholdTooHigh @@ -509,7 +525,7 @@ pub mod pallet { schedule.total_amount, )?; - let blocknumber_for_first_schedule_execution = Self::get_next_execution_block(start_execution_block)?; + let blocknumber_for_first_schedule_execution = Self::get_first_execution_block(start_execution_block)?; let mut randomness_generator = Self::get_randomness_generator( frame_system::Pallet::::current_block_number(), @@ -561,7 +577,7 @@ pub mod pallet { Self::try_unreserve_all(schedule_id, &schedule); - let next_execution_block = Self::get_next_execution_block(next_execution_block)?; + let next_execution_block = next_execution_block.ok_or(Error::::ScheduleNotFound)?; //Remove schedule id from next execution block ScheduleIdsPerBlock::::try_mutate_exists( @@ -609,7 +625,7 @@ impl Pallet { } } - fn get_next_execution_block( + fn get_first_execution_block( start_execution_block: Option>, ) -> Result, DispatchError> { let blocknumber_for_first_schedule_execution = match start_execution_block { @@ -638,6 +654,12 @@ impl Pallet { schedule: &Schedule>, randomness_generator: &mut StdRng, ) -> DispatchResult { + if Percent::from_percent(randomness_generator.gen_range(0..100)) <= T::BumpChance::get() { + let next_block = current_blocknumber.clone().saturating_add(1u32.into()); + Self::plan_schedule_for_block(&schedule.owner, next_block, schedule_id, randomness_generator)?; + return Err(Error::::Bumped.into()); + } + Self::take_transaction_fee_from_user(schedule_id, schedule, weight_for_dca_execution)?; if Self::is_price_unstable(schedule) { diff --git a/pallets/dca/src/tests/mock.rs b/pallets/dca/src/tests/mock.rs index 36b8f0230..c2fc19c36 100644 --- a/pallets/dca/src/tests/mock.rs +++ b/pallets/dca/src/tests/mock.rs @@ -34,12 +34,12 @@ use pallet_currencies::BasicCurrencyAdapter; use primitive_types::U128; use sp_core::H256; use sp_runtime::traits::{AccountIdConversion, BlockNumberProvider, ConstU32}; -use sp_runtime::Perbill; use sp_runtime::Permill; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup, One}, BuildStorage, DispatchError, }; +use sp_runtime::{Perbill, Percent}; use hydra_dx_math::support::rational::{round_to_rational, Rounding}; use sp_runtime::traits::Zero; @@ -643,6 +643,9 @@ parameter_types! { pub MinBudgetInNativeCurrency: Balance= MIN_BUDGET.with(|v| *v.borrow()); pub MaxSchedulePerBlock: u32 = 20; pub OmnipoolMaxAllowedPriceDifference: Permill = MAX_PRICE_DIFFERENCE.with(|v| *v.borrow()); + pub MaxConfigurablePriceDifference: Permill = Permill::from_percent(20); + pub MinimalPeriod: u32 = 5; + pub BumpChance: Percent = Percent::from_percent(17); pub NamedReserveId: NamedReserveIdentifier = *b"dcaorder"; pub MaxNumberOfRetriesOnError: u8 = 3; } @@ -676,6 +679,9 @@ impl Config for Test { type RouteExecutor = RouteExecutor; type RouteProvider = DefaultRouteProvider; type MaxPriceDifferenceBetweenBlocks = OmnipoolMaxAllowedPriceDifference; + type MaxConfigurablePriceDifferenceBetweenBlocks = MaxConfigurablePriceDifference; + type MinimalPeriod = MinimalPeriod; + type BumpChance = BumpChance; type NamedReserveId = NamedReserveId; type MaxNumberOfRetriesOnError = MaxNumberOfRetriesOnError; type TechnicalOrigin = EnsureRoot; diff --git a/runtime/hydradx/src/assets.rs b/runtime/hydradx/src/assets.rs index d417620d4..53d366c6a 100644 --- a/runtime/hydradx/src/assets.rs +++ b/runtime/hydradx/src/assets.rs @@ -42,7 +42,7 @@ use primitives::constants::{ currency::{NATIVE_EXISTENTIAL_DEPOSIT, UNITS}, time::DAYS, }; -use sp_runtime::{traits::Zero, DispatchError, DispatchResult, FixedPointNumber}; +use sp_runtime::{traits::Zero, DispatchError, DispatchResult, FixedPointNumber, Percent}; use core::ops::RangeInclusive; use frame_support::{ @@ -738,6 +738,9 @@ parameter_types! { pub MinBudgetInNativeCurrency: Balance = 1000 * UNITS; pub MaxSchedulesPerBlock: u32 = 20; pub MaxPriceDifference: Permill = Permill::from_rational(15u32, 1000u32); + pub MaxConfigurablePriceDifference: Permill = Permill::from_percent(5); + pub MinimalPeriod: u32 = 5; + pub BumpChance: Percent = Percent::from_percent(17); pub NamedReserveId: NamedReserveIdentifier = *b"dcaorder"; pub MaxNumberOfRetriesOnError: u8 = 3; pub DCAOraclePeriod: OraclePeriod = OraclePeriod::Short; @@ -773,6 +776,9 @@ impl pallet_dca::Config for Runtime { type RouteExecutor = pallet_route_executor::DummyRouter; type RouteProvider = Router; type MaxPriceDifferenceBetweenBlocks = MaxPriceDifference; + type MaxConfigurablePriceDifferenceBetweenBlocks = MaxConfigurablePriceDifference; + type MinimalPeriod = MinimalPeriod; + type BumpChance = BumpChance; type MaxSchedulePerBlock = MaxSchedulesPerBlock; type MaxNumberOfRetriesOnError = MaxNumberOfRetriesOnError; type NativeAssetId = NativeAssetId; From e466875df26b532325e42e5d6136af6ab9f3f872 Mon Sep 17 00:00:00 2001 From: mrq Date: Wed, 17 Jul 2024 16:11:27 +0200 Subject: [PATCH 05/17] makes sure you cannot manually specify next block even if its mod 5 = 0 --- pallets/dca/Cargo.toml | 39 ++++++++++++++++++++------------------- pallets/dca/src/lib.rs | 6 ++++-- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/pallets/dca/Cargo.toml b/pallets/dca/Cargo.toml index 4d3427ce4..a5e80a85c 100644 --- a/pallets/dca/Cargo.toml +++ b/pallets/dca/Cargo.toml @@ -19,6 +19,7 @@ codec = { default-features = false, features = ["derive"], package = "parity-sca # primitives sp-runtime = { workspace = true } sp-std = { workspace = true } +primitive-types = { version = "0.12.0", default-features = false } # FRAME frame-support = { workspace = true } @@ -26,13 +27,13 @@ frame-system = { workspace = true } #cumumlus cumulus-primitives-core = { workspace = true } -cumulus-pallet-parachain-system ={ workspace = true } +cumulus-pallet-parachain-system = { workspace = true } # HydraDX dependencies pallet-omnipool = { workspace = true } hydradx-traits = { workspace = true } hydradx-adapters = { workspace = true } -pallet-ema-oracle = { workspace = true } +pallet-ema-oracle = { workspace = true } hydra-dx-math = { workspace = true } @@ -44,7 +45,7 @@ frame-benchmarking = { workspace = true, optional = true } sp-core = { workspace = true, optional = true } sp-io = { workspace = true, optional = true } -primitives = { path="../../primitives", default-features = false } +primitives = { path = "../../primitives", default-features = false } [dev-dependencies] @@ -64,24 +65,24 @@ primitive-types = { version = "0.12.0", default-features = false } [features] default = ['std'] std = [ - 'codec/std', - 'frame-support/std', - 'frame-system/std', - 'sp-runtime/std', - 'sp-std/std', - 'sp-core/std', - 'sp-io/std', - "scale-info/std", - "orml-tokens/std", - "hydradx-traits/std", - "hydradx-adapters/std", - "pallet-omnipool/std", - "pallet-ema-oracle/std", + 'codec/std', + 'frame-support/std', + 'frame-system/std', + 'sp-runtime/std', + 'sp-std/std', + 'sp-core/std', + 'sp-io/std', + "scale-info/std", + "orml-tokens/std", + "hydradx-traits/std", + "hydradx-adapters/std", + "pallet-omnipool/std", + "pallet-ema-oracle/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index cb9e04d33..a60824f05 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -83,6 +83,7 @@ use hydradx_traits::NativePriceOracle; use hydradx_traits::OraclePeriod; use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; +use primitive_types::U256; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; @@ -628,14 +629,15 @@ impl Pallet { fn get_first_execution_block( start_execution_block: Option>, ) -> Result, DispatchError> { + let current_block_number = frame_system::Pallet::::current_block_number(); let blocknumber_for_first_schedule_execution = match start_execution_block { Some(blocknumber) => { - let remainder: u32 = (blocknumber.into() % 5).as_u32(); + let number: U256 = current_block_number.saturating_add(2u32.into()).max(blocknumber).into(); + let remainder: u32 = (number % 5).as_u32(); let diff = if remainder == 0 { 0 } else { 5u32 - remainder }; Ok(blocknumber.saturating_add(BlockNumberFor::::from(diff))) } None => { - let current_block_number = frame_system::Pallet::::current_block_number(); let next_block_number = current_block_number .checked_add(&BlockNumberFor::::from(2u32)) .ok_or(ArithmeticError::Overflow)?; From 5534662d87909b38bf9669299977a4f170cdf54b Mon Sep 17 00:00:00 2001 From: mrq Date: Wed, 17 Jul 2024 16:47:43 +0200 Subject: [PATCH 06/17] fixed first execution assigment --- pallets/dca/Cargo.toml | 1 - pallets/dca/src/lib.rs | 7 +++--- pallets/dca/src/tests/schedule.rs | 39 ++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/pallets/dca/Cargo.toml b/pallets/dca/Cargo.toml index a5e80a85c..20a79a7c5 100644 --- a/pallets/dca/Cargo.toml +++ b/pallets/dca/Cargo.toml @@ -19,7 +19,6 @@ codec = { default-features = false, features = ["derive"], package = "parity-sca # primitives sp-runtime = { workspace = true } sp-std = { workspace = true } -primitive-types = { version = "0.12.0", default-features = false } # FRAME frame-support = { workspace = true } diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index a60824f05..472912afd 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -83,7 +83,6 @@ use hydradx_traits::NativePriceOracle; use hydradx_traits::OraclePeriod; use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; -use primitive_types::U256; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; @@ -632,10 +631,10 @@ impl Pallet { let current_block_number = frame_system::Pallet::::current_block_number(); let blocknumber_for_first_schedule_execution = match start_execution_block { Some(blocknumber) => { - let number: U256 = current_block_number.saturating_add(2u32.into()).max(blocknumber).into(); - let remainder: u32 = (number % 5).as_u32(); + let number = current_block_number.saturating_add(2u32.into()).max(blocknumber); + let remainder: u32 = (number.into() % 5).as_u32(); let diff = if remainder == 0 { 0 } else { 5u32 - remainder }; - Ok(blocknumber.saturating_add(BlockNumberFor::::from(diff))) + Ok(number.saturating_add(diff.into())) } None => { let next_block_number = current_block_number diff --git a/pallets/dca/src/tests/schedule.rs b/pallets/dca/src/tests/schedule.rs index fe2f12c86..115123016 100644 --- a/pallets/dca/src/tests/schedule.rs +++ b/pallets/dca/src/tests/schedule.rs @@ -273,7 +273,7 @@ fn schedule_should_emit_necessary_events() { Event::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 501, + block: 502, } .into(), Event::Scheduled { @@ -288,6 +288,43 @@ fn schedule_should_emit_necessary_events() { }); } +#[test] +fn schedule_first_execution_cannot_be_next_block_manually() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) + .build() + .execute_with(|| { + //Arrange + let schedule = ScheduleBuilder::new().build(); + + //Act + set_block_number(500); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule.clone(), + Some(500000000000001) + )); + + //Assert + expect_events(vec![ + Event::ExecutionPlanned { + id: 0, + who: ALICE, + block: 505, + } + .into(), + Event::Scheduled { + id: 0, + who: ALICE, + period: schedule.period, + total_amount: schedule.total_amount, + order: schedule.order, + } + .into(), + ]); + }); +} + #[test] fn schedule_should_emit_necessary_events_when_multiple_schedules_are_created() { ExtBuilder::default() From c2523e8e4f44bcfd8dff2be5513dbfb6145d2c8c Mon Sep 17 00:00:00 2001 From: mrq Date: Wed, 17 Jul 2024 16:52:01 +0200 Subject: [PATCH 07/17] test fixed --- pallets/dca/src/tests/schedule.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pallets/dca/src/tests/schedule.rs b/pallets/dca/src/tests/schedule.rs index 115123016..b34c16738 100644 --- a/pallets/dca/src/tests/schedule.rs +++ b/pallets/dca/src/tests/schedule.rs @@ -299,11 +299,7 @@ fn schedule_first_execution_cannot_be_next_block_manually() { //Act set_block_number(500); - assert_ok!(DCA::schedule( - RuntimeOrigin::signed(ALICE), - schedule.clone(), - Some(500000000000001) - )); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule.clone(), Some(501))); //Assert expect_events(vec![ From 32f4593937d29c939a1395d3f6cbb09774171235 Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 18 Jul 2024 10:40:14 +0100 Subject: [PATCH 08/17] fix some tests --- pallets/dca/src/tests/on_initialize.rs | 203 ++++++++++--------------- pallets/democracy/src/lib.rs | 1 + 2 files changed, 84 insertions(+), 120 deletions(-) diff --git a/pallets/dca/src/tests/on_initialize.rs b/pallets/dca/src/tests/on_initialize.rs index f5f27dde4..65aa646f1 100644 --- a/pallets/dca/src/tests/on_initialize.rs +++ b/pallets/dca/src/tests/on_initialize.rs @@ -174,7 +174,7 @@ fn one_sell_dca_execution_should_unreserve_amount_in() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let remaining_named_reserve = total_amount - amount_to_sell - SELL_DCA_FEE_IN_NATIVE; @@ -199,7 +199,7 @@ fn one_sell_dca_execution_should_unreserve_amount_in() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 602, } .into(), ]) @@ -353,7 +353,7 @@ fn one_buy_dca_execution_should_unreserve_exact_amount_in() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_buy_trades!(vec![BuyExecution { @@ -411,7 +411,7 @@ fn one_buy_dca_execution_should_calculate_exact_amount_in_when_multiple_pools_in assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_buy_trades!(vec![ @@ -468,7 +468,7 @@ fn full_sell_dca_should_be_completed_with_selling_leftover_in_last_trade() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - proceed_to_blocknumber(501, 801); + proceed_to_blocknumber(502, 802); //Assert assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); @@ -530,7 +530,7 @@ fn full_sell_dca_should_be_completed_when_some_successful_dca_execution_happened proceed_to_blocknumber(1, 500); let amount_to_sell = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; - let total_amount = amount_to_sell + SELL_DCA_FEE_IN_NATIVE + SELL_DCA_FEE_IN_NATIVE / 2; + let total_amount = 2 * (amount_to_sell + SELL_DCA_FEE_IN_NATIVE) + SELL_DCA_FEE_IN_NATIVE / 2; let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) @@ -557,8 +557,8 @@ fn full_sell_dca_should_be_completed_when_some_successful_dca_execution_happened //Assert assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); - assert_number_of_executed_sell_trades!(1); - assert_balance!(ALICE, BTC, *AMOUNT_OUT_FOR_OMNIPOOL_SELL); + assert_number_of_executed_sell_trades!(2); + assert_balance!(ALICE, BTC, 2 * *AMOUNT_OUT_FOR_OMNIPOOL_SELL); let schedule_id = 0; assert_that_dca_is_completed(ALICE, schedule_id); @@ -617,7 +617,7 @@ fn full_buy_dca_should_be_completed_when_some_successful_dca_execution_happened_ proceed_to_blocknumber(1, 500); let total_amount = - CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY + BUY_DCA_FEE_IN_NATIVE + BUY_DCA_FEE_IN_NATIVE / 2; + 2 * (CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY + BUY_DCA_FEE_IN_NATIVE) + BUY_DCA_FEE_IN_NATIVE / 2; let amount_to_buy = 10 * ONE; let schedule = ScheduleBuilder::new() @@ -641,13 +641,13 @@ fn full_buy_dca_should_be_completed_when_some_successful_dca_execution_happened_ assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - proceed_to_blocknumber(501, 801); + proceed_to_blocknumber(502, 802); //Assert assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); - assert_number_of_executed_buy_trades!(1); - assert_balance!(ALICE, BTC, CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY); + assert_number_of_executed_buy_trades!(2); + assert_balance!(ALICE, BTC, 2*CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY); let schedule_id = 0; assert_that_dca_is_completed(ALICE, schedule_id); @@ -714,7 +714,7 @@ fn full_sell_dca_should_be_completed_for_multiple_users() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &BOB)); //Act - proceed_to_blocknumber(501, 801); + proceed_to_blocknumber(502, 802); //Assert assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); @@ -767,7 +767,7 @@ fn multiple_sell_dca_should_be_completed_for_one_user() { assert_eq!(total_amount + total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - proceed_to_blocknumber(501, 801); + proceed_to_blocknumber(502, 802); //Assert assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); @@ -958,7 +958,7 @@ fn one_buy_dca_execution_should_use_default_max_price_diff_for_max_limit_calcula assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_number_of_executed_buy_trades!(1); @@ -1008,13 +1008,13 @@ fn schedule_is_planned_for_next_block_when_one_execution_finished() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_number_of_executed_buy_trades!(1); let schedule_id = 0; - assert_scheduled_ids!(601, vec![schedule_id]); + assert_scheduled_ids!(602, vec![schedule_id]); }); } @@ -1053,13 +1053,13 @@ fn schedule_is_planned_with_period_when_block_has_already_planned_schedule() { proceed_to_blocknumber(1, 500); let schedule_id_2 = 1; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(501))); //Act - set_to_blocknumber(501); + set_to_blocknumber(505); //Assert - assert_scheduled_ids!(601, vec![schedule_id, schedule_id_2]); + assert_scheduled_ids!(605, vec![schedule_id, schedule_id_2]); }); } @@ -1091,13 +1091,13 @@ fn buy_dca_schedule_should_be_retried_when_trade_limit_error_happens() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); - set_to_blocknumber(501); + set_to_blocknumber(502); assert_number_of_executed_buy_trades!(0); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(1, retries); expect_dca_events(vec![ @@ -1110,7 +1110,7 @@ fn buy_dca_schedule_should_be_retried_when_trade_limit_error_happens() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 511, + block: 512, } .into(), ]); @@ -1202,10 +1202,10 @@ fn dca_trade_unallocation_should_be_rolled_back_when_trade_fails() { assert_eq!(Currencies::reserved_balance(HDX, &ALICE), total_amount); assert_eq!(DCA::remaining_amounts(schedule_id).unwrap(), total_amount); - set_to_blocknumber(501); + set_to_blocknumber(502); assert_number_of_executed_buy_trades!(0); - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); assert_eq!( Currencies::reserved_balance(HDX, &ALICE), @@ -1245,13 +1245,13 @@ fn dca_schedule_should_terminate_when_error_is_not_configured_to_continue_on() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let schedule_id = 0; assert_number_of_executed_buy_trades!(0); - assert!(DCA::schedule_ids_per_block(601).is_empty()); + assert!(DCA::schedule_ids_per_block(602).is_empty()); assert_that_dca_is_terminated(ALICE, schedule_id, pallet_omnipool::Error::::NotAllowed.into()); }); } @@ -1284,16 +1284,16 @@ fn dca_schedule_should_continue_on_multiple_failures_then_terminated() { //Act and assert let schedule_id = 0; - set_to_blocknumber(501); - assert_scheduled_ids!(511, vec![schedule_id]); + set_to_blocknumber(502); + assert_scheduled_ids!(512, vec![schedule_id]); - set_to_blocknumber(511); - assert_scheduled_ids!(531, vec![schedule_id]); + set_to_blocknumber(512); + assert_scheduled_ids!(532, vec![schedule_id]); - set_to_blocknumber(531); - assert_scheduled_ids!(571, vec![schedule_id]); + set_to_blocknumber(532); + assert_scheduled_ids!(572, vec![schedule_id]); - set_to_blocknumber(571); + set_to_blocknumber(572); assert!(DCA::schedules(schedule_id).is_none()); assert_number_of_executed_buy_trades!(0); }); @@ -1329,26 +1329,26 @@ fn dca_schedule_should_use_specified_max_retry_count() { //Act and assert let schedule_id = 0; - set_to_blocknumber(501); - assert_scheduled_ids!(511, vec![schedule_id]); + set_to_blocknumber(502); + assert_scheduled_ids!(512, vec![schedule_id]); - set_to_blocknumber(511); - assert_scheduled_ids!(531, vec![schedule_id]); + set_to_blocknumber(512); + assert_scheduled_ids!(532, vec![schedule_id]); - set_to_blocknumber(531); - assert_scheduled_ids!(571, vec![schedule_id]); + set_to_blocknumber(532); + assert_scheduled_ids!(572, vec![schedule_id]); - set_to_blocknumber(571); - assert_scheduled_ids!(651, vec![schedule_id]); + set_to_blocknumber(572); + assert_scheduled_ids!(652, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(4, retries); - set_to_blocknumber(651); - assert_scheduled_ids!(811, vec![schedule_id]); + set_to_blocknumber(652); + assert_scheduled_ids!(812, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(5, retries); - set_to_blocknumber(811); + set_to_blocknumber(812); assert!(DCA::schedules(schedule_id).is_none()); assert_number_of_executed_buy_trades!(0); }); @@ -1382,8 +1382,8 @@ fn buy_dca_schedule_should_continue_on_slippage_error() { //Act and assert let schedule_id = 0; - set_to_blocknumber(501); - assert_scheduled_ids!(511, vec![schedule_id]); + set_to_blocknumber(502); + assert_scheduled_ids!(512, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(1, retries); }); @@ -1462,16 +1462,16 @@ fn dca_schedule_retry_should_be_reset_when_successful_trade_after_failed_ones() //Act and assert let schedule_id = 0; - set_to_blocknumber(501); - assert_scheduled_ids!(511, vec![schedule_id]); + set_to_blocknumber(502); + assert_scheduled_ids!(512, vec![schedule_id]); - set_to_blocknumber(511); - assert_scheduled_ids!(531, vec![schedule_id]); + set_to_blocknumber(512); + assert_scheduled_ids!(532, vec![schedule_id]); set_max_price_diff(Permill::from_percent(10)); - set_to_blocknumber(531); - assert_scheduled_ids!(531 + ONE_HUNDRED_BLOCKS, vec![schedule_id]); + set_to_blocknumber(532); + assert_scheduled_ids!(532 + ONE_HUNDRED_BLOCKS, vec![schedule_id]); assert_number_of_executed_sell_trades!(1); let retries = DCA::retries_on_error(schedule_id); @@ -1510,7 +1510,7 @@ fn execution_fee_should_be_taken_from_user_in_sold_currency_in_case_of_successfu //Act assert_balance!(TreasuryAccount::get(), DAI, 0); - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_balance!(TreasuryAccount::get(), DAI, BUY_DCA_FEE_IN_DAI); @@ -1555,7 +1555,7 @@ fn execution_fee_should_be_still_taken_from_user_in_sold_currency_in_case_of_fai assert_balance!(TreasuryAccount::get(), DAI, 0); assert_balance!(ALICE, BTC, 0); - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_balance!(TreasuryAccount::get(), DAI, BUY_DCA_FEE_IN_DAI); @@ -1598,7 +1598,7 @@ fn execution_fee_should_be_taken_from_user_in_sold_currency_in_case_of_successfu //Act assert_balance!(TreasuryAccount::get(), DAI, 0); - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_balance!(TreasuryAccount::get(), DAI, SELL_DCA_FEE_IN_DAI); @@ -1729,7 +1729,7 @@ fn buy_dca_native_execution_fee_should_be_taken_and_sent_to_treasury() { assert_balance!(TreasuryAccount::get(), HDX, 0); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_balance!(TreasuryAccount::get(), HDX, BUY_DCA_FEE_IN_NATIVE); @@ -1813,11 +1813,11 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_max }) .build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(501))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, None)); assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_sell_trades!(vec![]); @@ -1827,7 +1827,7 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_max ); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); expect_dca_events(vec![ DcaEvent::TradeFailed { id: schedule_id, @@ -1838,7 +1838,7 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_max DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 511, + block: 512, } .into(), ]); @@ -1876,11 +1876,11 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_use }) .build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(501))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, None)); assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_sell_trades!(vec![]); @@ -1890,7 +1890,7 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_use ); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); expect_dca_events(vec![ DcaEvent::TradeFailed { id: schedule_id, @@ -1901,7 +1901,7 @@ fn one_sell_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_use DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 511, + block: 512, } .into(), ]); @@ -1942,7 +1942,7 @@ fn one_buy_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_max_ assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_buy_trades!(vec![]); @@ -1952,7 +1952,7 @@ fn one_buy_dca_execution_should_be_rescheduled_when_price_diff_is_more_than_max_ ); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); }); } @@ -2135,12 +2135,12 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque }) .build(); - let mut execution_block = 501; + let mut execution_block = 502; for _ in RangeInclusive::new(1, 220) { assert_ok!(DCA::schedule( RuntimeOrigin::signed(ALICE), schedule.clone(), - Option::Some(501) + None )); } @@ -2156,7 +2156,7 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque } //Act - proceed_to_blocknumber(501, 1524); + proceed_to_blocknumber(502, 1530); //Assert assert_number_of_executed_sell_trades!(1860); @@ -2168,45 +2168,6 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque }); } -#[test] -fn dca_sell_schedule_should_be_completed_after_one_trade_when_total_amount_is_equal_to_amount_in_plus_fee() { - ExtBuilder::default() - .with_endowed_accounts(vec![(ALICE, HDX, 5000 * ONE)]) - .build() - .execute_with(|| { - //Arrange - proceed_to_blocknumber(1, 500); - - let amount_in = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; - let total_amount = amount_in + SELL_DCA_FEE_IN_NATIVE; - let schedule = ScheduleBuilder::new() - .with_period(ONE_HUNDRED_BLOCKS) - .with_total_amount(total_amount) - .with_order(Order::Sell { - asset_in: HDX, - asset_out: BTC, - amount_in, - min_amount_out: Balance::MIN, - route: create_bounded_vec(vec![Trade { - pool: Omnipool, - asset_in: HDX, - asset_out: BTC, - }]), - }) - .build(); - - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); - - //Act - set_to_blocknumber(501); - - //Assert - let schedule_id = 0; - assert_number_of_executed_sell_trades!(1); - assert_that_dca_is_completed(ALICE, schedule_id); - }); -} - #[test] fn dca_sell_schedule_should_be_terminated_when_schedule_allocation_is_more_than_reserved_funds() { ExtBuilder::default() @@ -2217,7 +2178,7 @@ fn dca_sell_schedule_should_be_terminated_when_schedule_allocation_is_more_than_ proceed_to_blocknumber(1, 500); let amount_in = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; - let total_amount = amount_in + SELL_DCA_FEE_IN_NATIVE; + let total_amount = 2 * (amount_in + SELL_DCA_FEE_IN_NATIVE); let schedule = ScheduleBuilder::new() .with_period(ONE_HUNDRED_BLOCKS) .with_total_amount(total_amount) @@ -2236,10 +2197,10 @@ fn dca_sell_schedule_should_be_terminated_when_schedule_allocation_is_more_than_ assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); - Currencies::unreserve_named(&NamedReserveId::get(), HDX, &ALICE, ONE / 2); + Currencies::unreserve_named(&NamedReserveId::get(), HDX, &ALICE, 5000 * ONE); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let schedule_id = 0; @@ -2445,7 +2406,7 @@ fn dca_should_complete_when_remainder_is_smaller_than_min_trading_limit() { proceed_to_blocknumber(1, 500); let remainder = min_trade_limit - 1; - let total_amount = ONE + SELL_DCA_FEE_IN_NATIVE + remainder; + let total_amount = 2 * (ONE + SELL_DCA_FEE_IN_NATIVE) + remainder; let amount_to_sell = ONE; let schedule = ScheduleBuilder::new() @@ -2467,7 +2428,8 @@ fn dca_should_complete_when_remainder_is_smaller_than_min_trading_limit() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert let schedule_id = 0; @@ -2485,7 +2447,7 @@ fn dca_should_continue_when_remainder_is_equal_to_min_trading_limit() { //Arrange proceed_to_blocknumber(1, 500); - let total_amount = ONE + SELL_DCA_FEE_IN_NATIVE + min_trade_limit; + let total_amount = 2 * (ONE + SELL_DCA_FEE_IN_NATIVE) + min_trade_limit; let amount_to_sell = ONE; let schedule = ScheduleBuilder::new() @@ -2507,14 +2469,15 @@ fn dca_should_continue_when_remainder_is_equal_to_min_trading_limit() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert let schedule_id = 0; expect_events(vec![DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 702, } .into()]); }); @@ -2553,7 +2516,7 @@ fn execution_is_still_successful_when_no_parent_hash_present() { set_parent_hash(None); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let schedule_id = 0; @@ -2568,7 +2531,7 @@ fn execution_is_still_successful_when_no_parent_hash_present() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 602, } .into(), ]); @@ -2602,7 +2565,7 @@ fn dca_schedule_should_still_take_fee_when_order_fails() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act and assert - set_to_blocknumber(501); + set_to_blocknumber(502); assert_number_of_executed_buy_trades!(0); assert_balance!(TreasuryAccount::get(), HDX, BUY_DCA_FEE_IN_NATIVE); }); diff --git a/pallets/democracy/src/lib.rs b/pallets/democracy/src/lib.rs index 14a355812..be6572a0e 100644 --- a/pallets/democracy/src/lib.rs +++ b/pallets/democracy/src/lib.rs @@ -187,6 +187,7 @@ pub use types::{ pub use vote::{AccountVote, Vote, Voting}; pub use vote_threshold::{Approved, VoteThreshold}; pub use weights::WeightInfo; +use sp_std::vec; #[cfg(test)] mod tests; From 6ad5bc11b7775ffde5ea00633304c597b61a5eb7 Mon Sep 17 00:00:00 2001 From: dmoka Date: Fri, 19 Jul 2024 14:01:57 +0100 Subject: [PATCH 09/17] fix tests due to changed DCA implementation --- integration-tests/src/dca.rs | 151 +++++++----------- .../stableswap/tests/invariants.txt | 7 + pallets/dca/src/lib.rs | 76 +++++++-- pallets/dca/src/tests/mock.rs | 33 +++- pallets/dca/src/tests/on_initialize.rs | 121 +++++++------- pallets/dca/src/tests/schedule.rs | 97 +++-------- pallets/dca/src/tests/terminate.rs | 29 +--- 7 files changed, 239 insertions(+), 275 deletions(-) create mode 100644 math/proptest-regressions/stableswap/tests/invariants.txt diff --git a/integration-tests/src/dca.rs b/integration-tests/src/dca.rs index 6d146769f..24b0ffbdc 100644 --- a/integration-tests/src/dca.rs +++ b/integration-tests/src/dca.rs @@ -61,7 +61,7 @@ mod omnipool { let schedule = DCA::schedules(schedule_id); assert!(schedule.is_some()); - let next_block_id = block_id + 1; + let next_block_id = block_id + 2; let schedule = DCA::schedule_ids_per_block(next_block_id); assert!(!schedule.is_empty()); expect_hydra_last_events(vec![pallet_dca::Event::Scheduled { @@ -96,7 +96,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -131,7 +131,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -158,7 +158,7 @@ mod omnipool { let amount_out = 100 * UNITS; let schedule1 = Schedule { owner: AccountId::from(ALICE), - period: 1u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -183,7 +183,7 @@ mod omnipool { //Act and assert let schedule_id = 0; - set_relaychain_block_number(11); + set_relaychain_block_number(12); let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); @@ -191,20 +191,20 @@ mod omnipool { assert_reserved_balance!(&ALICE.into(), HDX, dca_budget - fee); assert_eq!(DCA::retries_on_error(schedule_id), 1); - set_relaychain_block_number(21); + set_relaychain_block_number(22); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_balance!(ALICE.into(), HDX, ALICE_INITIAL_NATIVE_BALANCE - dca_budget); assert_reserved_balance!(&ALICE.into(), HDX, dca_budget - 2 * fee); assert_eq!(DCA::retries_on_error(schedule_id), 2); - set_relaychain_block_number(41); + set_relaychain_block_number(42); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_balance!(ALICE.into(), HDX, ALICE_INITIAL_NATIVE_BALANCE - dca_budget); assert_reserved_balance!(&ALICE.into(), HDX, dca_budget - 3 * fee); assert_eq!(DCA::retries_on_error(schedule_id), 3); //After this retry we terminate - set_relaychain_block_number(81); + set_relaychain_block_number(82); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_balance!(ALICE.into(), HDX, ALICE_INITIAL_NATIVE_BALANCE - 4 * fee); assert_reserved_balance!(&ALICE.into(), HDX, 0); @@ -236,7 +236,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), LRNA, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(LRNA, &Treasury::account_id()); @@ -270,7 +270,7 @@ mod omnipool { create_schedule(ALICE, schedule1); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -355,7 +355,7 @@ mod omnipool { create_schedule(ALICE, schedule1); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(LRNA, &Treasury::account_id()); @@ -440,7 +440,7 @@ mod omnipool { assert_reserved_balance!(&ALICE.into(), HDX, dca_budget); //Act - run_to_block(11, 40); + run_to_block(11, 50); //Assert assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE + 700 * UNITS); @@ -483,7 +483,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let amount_out = 71_214_372_591_631; @@ -519,7 +519,7 @@ mod omnipool { BOB.into(), )); - rococo_run_to_block(11); + rococo_run_to_block(12); let alice_init_hdx_balance = 5000 * UNITS; assert_ok!(Balances::force_set_balance( @@ -565,7 +565,7 @@ mod omnipool { ETH, BOB.into(), )); - rococo_run_to_block(12); + rococo_run_to_block(14); //Assert let schedule_id = 0; @@ -575,43 +575,6 @@ mod omnipool { }); } - #[test] - fn sell_schedule_should_sell_remaining_in_next_trade_when_there_is_not_enough_left() { - TestNet::reset(); - Hydra::execute_with(|| { - //Arrange - init_omnipool_with_oracle_for_block_10(); - let alice_init_hdx_balance = 5000 * UNITS; - assert_ok!(Balances::force_set_balance( - RuntimeOrigin::root(), - ALICE.into(), - alice_init_hdx_balance, - )); - - let dca_budget = 1000 * UNITS; - let amount_to_sell = 700 * UNITS; - let schedule1 = - schedule_fake_with_sell_order(ALICE, PoolType::Omnipool, dca_budget, HDX, DAI, amount_to_sell); - create_schedule(ALICE, schedule1); - - assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); - assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); - assert_reserved_balance!(&ALICE.into(), HDX, dca_budget); - assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); - - //Act - run_to_block(11, 15); - - //Assert - let schedule_id = 0; - let schedule = DCA::schedules(schedule_id); - assert!(schedule.is_none()); - - assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); - assert_reserved_balance!(&ALICE.into(), HDX, 0); - }); - } - #[test] fn sell_schedule_execution_should_work_without_route() { TestNet::reset(); @@ -641,7 +604,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -670,7 +633,7 @@ mod omnipool { let amount_to_sell = 100 * UNITS; let schedule1 = Schedule { owner: AccountId::from(ALICE), - period: 1u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -696,7 +659,7 @@ mod omnipool { //Act and Assert let schedule_id = 0; - set_relaychain_block_number(11); + set_relaychain_block_number(12); let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); @@ -705,20 +668,20 @@ mod omnipool { assert_eq!(DCA::retries_on_error(schedule_id), 1); - set_relaychain_block_number(21); + set_relaychain_block_number(22); assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_reserved_balance!(&ALICE.into(), HDX, dca_budget - 2 * fee); assert_eq!(DCA::retries_on_error(schedule_id), 2); - set_relaychain_block_number(41); + set_relaychain_block_number(42); assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_reserved_balance!(&ALICE.into(), HDX, dca_budget - 3 * fee); assert_eq!(DCA::retries_on_error(schedule_id), 3); //At this point, the schedule will be terminated as retries max number of times - set_relaychain_block_number(81); + set_relaychain_block_number(82); assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - 4 * fee); assert_reserved_balance!(&ALICE.into(), HDX, 0); @@ -750,7 +713,7 @@ mod omnipool { assert_balance!(&Treasury::account_id(), LRNA, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let amount_out = 142499995765917; @@ -791,7 +754,7 @@ mod omnipool { assert_reserved_balance!(&ALICE.into(), HDX, dca_budget); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -882,7 +845,7 @@ mod omnipool { assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(LRNA, &Treasury::account_id()); @@ -1178,14 +1141,14 @@ mod omnipool { }) .unwrap(); - let alice_init_hdx_balance = 1000 * UNITS + fee + 1; + let alice_init_hdx_balance = 2 * (1000 * UNITS + fee) + 1; assert_ok!(Balances::force_set_balance( RuntimeOrigin::root(), ALICE.into(), alice_init_hdx_balance, )); - let dca_budget = 1000 * UNITS + fee; + let dca_budget = 2 * (1000 * UNITS + fee); let schedule1 = schedule_fake_with_sell_order(ALICE, PoolType::Omnipool, dca_budget, HDX, DAI, amount_to_sell); create_schedule(ALICE, schedule1); @@ -1196,12 +1159,12 @@ mod omnipool { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + run_to_block(11, 17); //Assert check_if_no_failed_events(); - assert_balance!(ALICE.into(), HDX, 0); assert_reserved_balance!(&ALICE.into(), HDX, 0); + assert_balance!(ALICE.into(), HDX, 0); }); } } @@ -1266,7 +1229,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), asset_a, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(asset_a, &Treasury::account_id()); @@ -1338,7 +1301,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), asset_a, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(asset_a, &Treasury::account_id()); @@ -1420,7 +1383,7 @@ mod stableswap { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -1442,7 +1405,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -1700,7 +1663,7 @@ mod stableswap { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -1722,7 +1685,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), stable_asset_1, 0); //Act - set_relaychain_block_number(1001); + set_relaychain_block_number(1002); //Assert let fee = Currencies::free_balance(stable_asset_1, &Treasury::account_id()); @@ -2008,7 +1971,7 @@ mod stableswap { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2030,7 +1993,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -2089,7 +2052,7 @@ mod stableswap { amount_to_buy, dca_budget, ); - set_relaychain_block_number(10); + set_relaychain_block_number(12); create_schedule(ALICE, schedule1); @@ -2099,7 +2062,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), asset_a, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(14); //Assert let fee = Currencies::free_balance(asset_a, &Treasury::account_id()); @@ -2189,7 +2152,7 @@ mod stableswap { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2211,7 +2174,7 @@ mod stableswap { assert_balance!(&Treasury::account_id(), stable_asset_1, 0); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(stable_asset_1, &Treasury::account_id()); @@ -2285,7 +2248,7 @@ mod xyk { let treasury_init_balance = Balances::free_balance(Treasury::account_id()); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let amount_out = 151105924242426; @@ -2339,7 +2302,7 @@ mod xyk { assert_reserved_balance!(&ALICE.into(), HDX, dca_budget); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert assert_balance!(ALICE.into(), DAI, ALICE_INITIAL_DAI_BALANCE + amount_to_buy); @@ -2442,7 +2405,7 @@ mod all_pools { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2468,7 +2431,7 @@ mod all_pools { ); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let amount_to_receive = 380211607465242; @@ -2590,7 +2553,7 @@ mod with_onchain_route { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2612,7 +2575,7 @@ mod with_onchain_route { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance - dca_budget); @@ -2704,7 +2667,7 @@ mod with_onchain_route { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2726,7 +2689,7 @@ mod with_onchain_route { assert_balance!(&Treasury::account_id(), HDX, TREASURY_ACCOUNT_INIT_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(HDX, &Treasury::account_id()) - TREASURY_ACCOUNT_INIT_BALANCE; @@ -2788,7 +2751,7 @@ mod with_onchain_route { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2831,7 +2794,7 @@ mod with_onchain_route { assert_balance!(ALICE.into(), HDX, ALICE_INITIAL_NATIVE_BALANCE); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(DOT, &Treasury::account_id()); @@ -2935,7 +2898,7 @@ mod with_onchain_route { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -2972,7 +2935,7 @@ mod with_onchain_route { create_schedule(ALICE, schedule); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(stable_asset_1, &Treasury::account_id()); @@ -3055,7 +3018,7 @@ mod with_onchain_route { let schedule = Schedule { owner: AccountId::from(ALICE), - period: 3u32, + period: 5u32, total_amount: dca_budget, max_retries: None, stability_threshold: None, @@ -3092,13 +3055,13 @@ mod with_onchain_route { create_schedule(ALICE, schedule); //Act - set_relaychain_block_number(11); + set_relaychain_block_number(12); //Assert let fee = Currencies::free_balance(DOT, &Treasury::account_id()); assert!(fee > 0, "The treasury did not receive the fee"); - assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance + 277_665_116_680_343); + assert_balance!(ALICE.into(), HDX, alice_init_hdx_balance + 277781714835263); assert_reserved_balance!(&ALICE.into(), DOT, dca_budget - amount_to_sell - fee); }); } @@ -3160,7 +3123,7 @@ fn schedule_fake_with_buy_order_with_route( ) -> Schedule { Schedule { owner: AccountId::from(ALICE), - period: 2u32, + period: 5u32, total_amount: budget, max_retries: None, stability_threshold: None, @@ -3207,7 +3170,7 @@ fn schedule_fake_with_sell_order_with_route( ) -> Schedule { Schedule { owner: AccountId::from(owner), - period: 3u32, + period: 5u32, total_amount, max_retries: None, stability_threshold: None, diff --git a/math/proptest-regressions/stableswap/tests/invariants.txt b/math/proptest-regressions/stableswap/tests/invariants.txt new file mode 100644 index 000000000..4988cffb0 --- /dev/null +++ b/math/proptest-regressions/stableswap/tests/invariants.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 856506ae58747f1a2ab6af2afe18b3689666b7046416552f394b37600f915570 # shrinks to pool = [AssetReserve { amount: 10000000000, decimals: 6 }, AssetReserve { amount: 34164000000, decimals: 6 }, AssetReserve { amount: 556700554000000, decimals: 6 }, AssetReserve { amount: 709227553000000, decimals: 6 }], amount = 350, amp = 7326, (idx_in, idx_out) = (2, 0) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index 472912afd..97f5533ac 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -85,6 +85,7 @@ use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; +use sp_std::boxed::Box; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; use sp_runtime::traits::CheckedMul; use sp_runtime::{ @@ -137,7 +138,7 @@ pub mod pallet { let mut schedule_ids: Vec = ScheduleIdsPerBlock::::take(current_blocknumber).to_vec(); - schedule_ids.sort_by_cached_key(|_| randomness_generator.gen::()); + schedule_ids.sort_by_cached_key(|_| randomness_generator.gen_u32()); for schedule_id in schedule_ids { Self::deposit_event(Event::ExecutionStarted { id: schedule_id, @@ -163,6 +164,7 @@ pub mod pallet { continue; } else { Self::terminate_schedule(schedule_id, &schedule, e); + continue; } }; @@ -612,7 +614,7 @@ pub mod pallet { } impl Pallet { - fn get_randomness_generator(current_blocknumber: BlockNumberFor, salt: Option) -> StdRng { + fn get_randomness_generator(current_blocknumber: BlockNumberFor, salt: Option) -> Box { match T::RandomnessProvider::generator(salt) { Ok(generator) => generator, Err(err) => { @@ -620,7 +622,13 @@ impl Pallet { block: current_blocknumber, error: err, }); - rand::rngs::StdRng::seed_from_u64(0) + + let randomness_generator : RandomnessGenerator = RandomnessGenerator { + rng: rand::rngs::StdRng::seed_from_u64(0), + _marker: Default::default(), + }; + + Box::new(randomness_generator) } } } @@ -653,10 +661,10 @@ impl Pallet { weight_for_dca_execution: Weight, schedule_id: ScheduleId, schedule: &Schedule>, - randomness_generator: &mut StdRng, + randomness_generator: &mut Box, ) -> DispatchResult { - if Percent::from_percent(randomness_generator.gen_range(0..100)) <= T::BumpChance::get() { - let next_block = current_blocknumber.clone().saturating_add(1u32.into()); + if Percent::from_percent(randomness_generator.gen_range_u8(0..100)) <= T::BumpChance::get() { + let next_block = current_blocknumber.saturating_add(1u32.into()); Self::plan_schedule_for_block(&schedule.owner, next_block, schedule_id, randomness_generator)?; return Err(Error::::Bumped.into()); } @@ -775,7 +783,7 @@ impl Pallet { schedule: &Schedule>, current_blocknumber: BlockNumberFor, amounts: AmountInAndOut, - randomness_generator: &mut StdRng, + randomness_generator: &mut Box, ) -> DispatchResult { Self::deposit_event(Event::TradeExecuted { id: schedule_id, @@ -823,7 +831,7 @@ impl Pallet { schedule_id: ScheduleId, schedule: &Schedule>, current_blocknumber: BlockNumberFor, - randomness_generator: &mut StdRng, + randomness_generator: &mut Box, ) -> DispatchResult { let number_of_retries = Self::retries_on_error(schedule_id); @@ -1007,7 +1015,7 @@ impl Pallet { who: &T::AccountId, blocknumber: BlockNumberFor, schedule_id: ScheduleId, - randomness_generator: &mut StdRng, + randomness_generator: &mut Box, ) -> DispatchResult { let current_block_number = frame_system::Pallet::::current_block_number(); ensure!(blocknumber > current_block_number, Error::::BlockNumberIsNotInFuture); @@ -1031,7 +1039,7 @@ impl Pallet { fn find_next_free_block( blocknumber: BlockNumberFor, - randomness_generator: &mut StdRng, + randomness_generator: &mut Box, ) -> Result, DispatchError> { let mut next_execution_block = blocknumber; @@ -1044,7 +1052,7 @@ impl Pallet { let lower_bound = 2u32.saturating_pow(i); let upper_bound = 2u32.saturating_pow(i.saturating_add(1)).saturating_sub(1); - let delay_with = randomness_generator.gen_range(lower_bound..=upper_bound); + let delay_with = randomness_generator.gen_range_u32(lower_bound..=upper_bound); next_execution_block = next_execution_block.saturating_add(delay_with.into()); } @@ -1129,15 +1137,34 @@ impl Pallet { } pub trait RandomnessProvider { - fn generator(salt: Option) -> Result; + fn generator(salt: Option) -> Result, DispatchError>; } impl RandomnessProvider for Pallet { - fn generator(salt: Option) -> Result { + fn generator(salt: Option) -> Result, DispatchError> { + let res = RandomnessGenerator::::new(salt)?; + + Ok(Box::new(res)) + } +} + +pub trait RandomNumberGenerator { + fn gen_u32(&mut self) -> u32; + fn gen_range_u8(&mut self, range: sp_std::ops::Range) -> u8; + fn gen_range_u32(&mut self, range: sp_std::ops::RangeInclusive) -> u32; +} + +pub struct RandomnessGenerator { + rng: StdRng, + _marker: sp_std::marker::PhantomData, +} + +impl RandomnessGenerator { + pub fn new(salt: Option) -> Result { let hash_value = T::RelayChainBlockHashProvider::parent_hash().ok_or(Error::::NoParentHashFound)?; let hash_bytes = hash_value.as_fixed_bytes(); let mut seed_arr = [0u8; 8]; - let max_len = hash_bytes.len().min(seed_arr.len()); //We ensure that we don't copy more bytes, preventing potential panics + let max_len = hash_bytes.len().min(seed_arr.len()); // Ensure we don't copy more bytes, preventing potential panics seed_arr[..max_len].copy_from_slice(&hash_bytes[..max_len]); let seed = match salt { @@ -1145,6 +1172,25 @@ impl RandomnessProvider for Pallet { None => u64::from_le_bytes(seed_arr), }; - Ok(rand::rngs::StdRng::seed_from_u64(seed)) + Ok(RandomnessGenerator { + rng: rand::rngs::StdRng::seed_from_u64(seed), + _marker: sp_std::marker::PhantomData, + }) + } +} + +impl RandomNumberGenerator for RandomnessGenerator { + fn gen_u32(&mut self) -> u32 { + self.rng.gen::() + } + + fn gen_range_u8(&mut self, range: sp_std::ops::Range) -> u8 + { + self.rng.gen_range(range) + } + + fn gen_range_u32(&mut self, range: sp_std::ops::RangeInclusive) -> u32 + { + self.rng.gen_range(range) } } diff --git a/pallets/dca/src/tests/mock.rs b/pallets/dca/src/tests/mock.rs index c2fc19c36..a129c0756 100644 --- a/pallets/dca/src/tests/mock.rs +++ b/pallets/dca/src/tests/mock.rs @@ -16,7 +16,7 @@ // limitations under the License. use crate as dca; -use crate::{Config, Error, RandomnessProvider, RelayChainBlockHashProvider}; +use crate::{Config, Error, RandomnessGenerator, RandomnessProvider, RelayChainBlockHashProvider, RandomNumberGenerator}; use cumulus_primitives_core::relay_chain::Hash; use frame_support::traits::{Everything, Nothing}; use frame_support::weights::constants::ExtrinsicBaseWeight; @@ -46,6 +46,7 @@ use sp_runtime::traits::Zero; use sp_runtime::{DispatchResult, FixedU128}; use std::cell::RefCell; use std::collections::HashMap; +use std::ops::{Range, RangeInclusive}; type Block = frame_system::mocking::MockBlock; @@ -67,8 +68,8 @@ pub const FORBIDDEN_ASSET: AssetId = 4; pub const REGISTERED_ASSET: AssetId = 1000; pub const ONE_HUNDRED_BLOCKS: BlockNumber = 100; -//Since we always use the same parent hash in the tests, the generated radiuses are always the same -pub const GENERATED_SEARCH_RADIUSES: [u64; 10] = [1, 3, 6, 10, 28, 34, 114, 207, 504, 947]; +//Since we always return 5 in the MockRndGenerator, therefore the delay is the same +pub const DELAYS: [u64; 10] = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]; pub const ONE: Balance = 1_000_000_000_000; @@ -653,17 +654,35 @@ parameter_types! { pub struct RandomnessProviderMock {} impl RandomnessProvider for RandomnessProviderMock { - fn generator(salt: Option) -> Result { + fn generator(salt: Option) -> Result, DispatchError> { let use_prod_randomness = USE_PROD_RANDOMNESS.with(|v| *v.borrow()); if use_prod_randomness { - DCA::generator(salt) + let gen = RandomnessGenerator::::new(salt).unwrap(); + Ok(Box::new(gen)) } else { - Ok(StdRng::seed_from_u64(0)) + Ok(Box::new(MockRndGenerator{})) } } } +pub struct MockRndGenerator; + +impl RandomNumberGenerator for MockRndGenerator { + fn gen_u32(&mut self) -> u32 { + 1 + } + + fn gen_range_u8(&mut self, _range: Range) -> u8 { + 18 + } + + fn gen_range_u32(&mut self, _range: RangeInclusive) -> u32 { + 5 + } +} + + impl Config for Test { type RuntimeEvent = RuntimeEvent; type AssetId = AssetId; @@ -721,8 +740,6 @@ use hydra_dx_math::types::Ratio; use hydradx_traits::router::{ExecutorError, PoolType, RefundEdCalculator, RouteProvider, Trade, TradeExecution}; use pallet_currencies::fungibles::FungibleCurrencies; use pallet_omnipool::traits::ExternalPriceProvider; -use rand::prelude::StdRng; -use rand::SeedableRng; use smallvec::smallvec; pub struct DummyNFT; diff --git a/pallets/dca/src/tests/on_initialize.rs b/pallets/dca/src/tests/on_initialize.rs index 65aa646f1..370b8d48c 100644 --- a/pallets/dca/src/tests/on_initialize.rs +++ b/pallets/dca/src/tests/on_initialize.rs @@ -64,7 +64,7 @@ fn successful_sell_dca_execution_should_emit_trade_executed_event() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let schedule_id = 0; @@ -79,7 +79,7 @@ fn successful_sell_dca_execution_should_emit_trade_executed_event() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 602, } .into(), ]); @@ -119,7 +119,7 @@ fn successful_buy_dca_execution_should_emit_trade_executed_event() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert let schedule_id = 0; @@ -134,7 +134,7 @@ fn successful_buy_dca_execution_should_emit_trade_executed_event() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 602, } .into(), ]); @@ -216,7 +216,7 @@ fn sell_schedule_should_sell_remaining_when_there_is_not_enough_left() { //Arrange proceed_to_blocknumber(1, 500); - let total_amount = *AMOUNT_OUT_FOR_OMNIPOOL_SELL * 3 / 2; + let total_amount = *AMOUNT_OUT_FOR_OMNIPOOL_SELL * 5 / 2; let amount_to_sell = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; let schedule = ScheduleBuilder::new() @@ -239,17 +239,13 @@ fn sell_schedule_should_sell_remaining_when_there_is_not_enough_left() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert - assert_executed_sell_trades!(vec![SellExecution { - asset_in: HDX, - asset_out: BTC, - amount_in: *AMOUNT_OUT_FOR_OMNIPOOL_SELL, - min_buy_amount: *AMOUNT_OUT_FOR_OMNIPOOL_SELL, - }]); + assert_number_of_executed_sell_trades!(2); - set_to_blocknumber(601); + set_to_blocknumber(702); //Assert assert_executed_sell_trades!(vec![ @@ -262,7 +258,13 @@ fn sell_schedule_should_sell_remaining_when_there_is_not_enough_left() { SellExecution { asset_in: HDX, asset_out: BTC, - amount_in: total_amount - amount_to_sell - SELL_DCA_FEE_IN_NATIVE - SELL_DCA_FEE_IN_NATIVE, + amount_in: *AMOUNT_OUT_FOR_OMNIPOOL_SELL, + min_buy_amount: *AMOUNT_OUT_FOR_OMNIPOOL_SELL, + }, + SellExecution { + asset_in: HDX, + asset_out: BTC, + amount_in: total_amount - 2 * (amount_to_sell + SELL_DCA_FEE_IN_NATIVE) - SELL_DCA_FEE_IN_NATIVE, min_buy_amount: *AMOUNT_OUT_FOR_OMNIPOOL_SELL, } ]); @@ -282,12 +284,12 @@ fn sell_schedule_should_continue_when_there_is_exact_amount_in_left_as_remaining //Arrange proceed_to_blocknumber(1, 500); - let total_amount = *AMOUNT_OUT_FOR_OMNIPOOL_SELL * 2 + SELL_DCA_FEE_IN_NATIVE; + let total_amount = 3 * *AMOUNT_OUT_FOR_OMNIPOOL_SELL * 2 + SELL_DCA_FEE_IN_NATIVE; let amount_to_sell = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) - .with_period(1) + .with_period(5) .with_order(Order::Sell { asset_in: HDX, asset_out: BTC, @@ -305,7 +307,8 @@ fn sell_schedule_should_continue_when_there_is_exact_amount_in_left_as_remaining assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(504); //Assert assert_executed_sell_trades!(vec![SellExecution { @@ -1145,12 +1148,12 @@ fn sell_dca_schedule_should_be_retried_when_trade_limit_error_happens() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); - set_to_blocknumber(501); + set_to_blocknumber(502); assert_number_of_executed_sell_trades!(0); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(1, retries); expect_dca_events(vec![ @@ -1163,7 +1166,7 @@ fn sell_dca_schedule_should_be_retried_when_trade_limit_error_happens() { DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 511, + block: 512, } .into(), ]); @@ -1422,8 +1425,8 @@ fn sell_dca_schedule_continue_on_slippage_error() { //Act and assert let schedule_id = 0; - set_to_blocknumber(501); - assert_scheduled_ids!(511, vec![schedule_id]); + set_to_blocknumber(502); + assert_scheduled_ids!(512, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(1, retries); }); @@ -1644,7 +1647,7 @@ fn sell_dca_native_execution_fee_should_be_taken_and_sent_to_treasury() { assert_balance!(TreasuryAccount::get(), HDX, 0); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_balance!(TreasuryAccount::get(), HDX, SELL_DCA_FEE_IN_NATIVE); @@ -1658,7 +1661,7 @@ fn sell_dca_native_execution_fee_should_be_taken_and_sent_to_treasury() { } #[test] -fn sell_dca_should_be_completed_when_trade_amount_is_total_budget_plus_fee() { +fn sell_dca_should_be_completed_when_last_trade_amount_is_total_budget_plus_fee() { ExtBuilder::default() .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) .build() @@ -1667,7 +1670,7 @@ fn sell_dca_should_be_completed_when_trade_amount_is_total_budget_plus_fee() { proceed_to_blocknumber(1, 500); let amount_to_sell = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; - let total_amount = amount_to_sell + SELL_DCA_FEE_IN_NATIVE; + let total_amount = 2 * (amount_to_sell + SELL_DCA_FEE_IN_NATIVE); let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) @@ -1690,10 +1693,11 @@ fn sell_dca_should_be_completed_when_trade_amount_is_total_budget_plus_fee() { assert_balance!(TreasuryAccount::get(), HDX, 0); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert - assert_number_of_executed_sell_trades!(1); + assert_number_of_executed_sell_trades!(2); assert_that_dca_is_completed(ALICE, 0); }); } @@ -1773,7 +1777,7 @@ fn slippage_limit_should_be_used_for_buy_dca_when_it_is_smaller_than_specified_t assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert //No trade happens because slippage limit is too small @@ -1990,7 +1994,7 @@ fn specified_slippage_should_be_used_in_circuit_breaker_price_check() { assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); //Assert assert_executed_buy_trades!(vec![]); @@ -2000,7 +2004,7 @@ fn specified_slippage_should_be_used_in_circuit_breaker_price_check() { ); let schedule_id = 0; - assert_scheduled_ids!(511, vec![schedule_id]); + assert_scheduled_ids!(512, vec![schedule_id]); let retries = DCA::retries_on_error(schedule_id); assert_eq!(1, retries); @@ -2018,12 +2022,11 @@ fn dca_should_be_terminated_when_dca_cannot_be_planned_due_to_not_free_blocks() let total_amount = 5 * *AMOUNT_OUT_FOR_OMNIPOOL_SELL; let amount_to_sell = *AMOUNT_OUT_FOR_OMNIPOOL_SELL; - let one_block = 1; let schedule_id = 0; let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) - .with_period(one_block) + .with_period(5) .with_order(Order::Sell { asset_in: HDX, asset_out: BTC, @@ -2037,16 +2040,16 @@ fn dca_should_be_terminated_when_dca_cannot_be_planned_due_to_not_free_blocks() }) .build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(995))); assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(502))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); } //Act - set_to_blocknumber(501); + set_to_blocknumber(995); //Assert assert_executed_sell_trades!(vec![SellExecution { @@ -2076,7 +2079,7 @@ fn dca_should_be_terminated_when_price_change_is_big_but_no_free_blocks_to_repla let schedule_id = 0; let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) - .with_period(1) + .with_period(5) .with_order(Order::Sell { asset_in: HDX, asset_out: BTC, @@ -2090,16 +2093,21 @@ fn dca_should_be_terminated_when_price_change_is_big_but_no_free_blocks_to_repla }) .build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(501))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(995))); assert_eq!(total_amount, Currencies::reserved_balance(HDX, &ALICE)); for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(511))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + } + + for _ in RangeInclusive::new(1, 20) { + let schedule = ScheduleBuilder::new().build(); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1055))); } //Act - set_to_blocknumber(501); + set_to_blocknumber(995); //Assert assert_executed_sell_trades!(vec![]); @@ -2135,31 +2143,31 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque }) .build(); - let mut execution_block = 502; for _ in RangeInclusive::new(1, 220) { assert_ok!(DCA::schedule( RuntimeOrigin::signed(ALICE), schedule.clone(), - None + Some(1000) )); } //Check if first block is fully filled + let mut execution_block = 1000; let actual_schedule_ids = DCA::schedule_ids_per_block(execution_block); assert_eq!(20, actual_schedule_ids.len()); //Check if all blocks found within radius are filled - for delay in GENERATED_SEARCH_RADIUSES { + for delay in DELAYS { execution_block += delay; let actual_schedule_ids = DCA::schedule_ids_per_block(execution_block); assert_eq!(20, actual_schedule_ids.len()); } //Act - proceed_to_blocknumber(502, 1530); + proceed_to_blocknumber(1000, 2000); //Assert - assert_number_of_executed_sell_trades!(1860); + assert_number_of_executed_sell_trades!(2220); //Assert if none of the schedule is terminated for schedule_id in RangeInclusive::new(0, 119) { @@ -2219,7 +2227,7 @@ fn sell_schedule_should_be_completed_when_remainder_is_less_than_20_transaction_ proceed_to_blocknumber(1, 500); let remainder = 20 * SELL_DCA_FEE_IN_NATIVE - 1; - let total_amount = ONE + SELL_DCA_FEE_IN_NATIVE + remainder; + let total_amount = 2 * (ONE + SELL_DCA_FEE_IN_NATIVE) + remainder; let amount_to_sell = ONE; let schedule = ScheduleBuilder::new() @@ -2241,7 +2249,8 @@ fn sell_schedule_should_be_completed_when_remainder_is_less_than_20_transaction_ assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert let schedule_id = 0; @@ -2290,12 +2299,12 @@ fn schedules_are_purged_when_the_block_is_over() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); - assert_number_of_executed_sell_trades!(3); set_to_blocknumber(502); + assert_number_of_executed_sell_trades!(3); + set_to_blocknumber(503); //Assert - let scheduled_ids_for_next_block = DCA::schedule_ids_per_block(501); + let scheduled_ids_for_next_block = DCA::schedule_ids_per_block(502); assert_eq!( scheduled_ids_for_next_block, create_bounded_vec_with_schedule_ids(vec![]) @@ -2313,7 +2322,7 @@ fn sell_schedule_should_be_replanned_when_remainder_is_equal_to_20_transaction_f proceed_to_blocknumber(1, 500); let remainder = 20 * SELL_DCA_FEE_IN_NATIVE; - let total_amount = ONE + SELL_DCA_FEE_IN_NATIVE + remainder; + let total_amount = 2 * (ONE + SELL_DCA_FEE_IN_NATIVE) + remainder; let amount_to_sell = ONE; let schedule = ScheduleBuilder::new() @@ -2335,14 +2344,15 @@ fn sell_schedule_should_be_replanned_when_remainder_is_equal_to_20_transaction_f assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert let schedule_id = 0; expect_events(vec![DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 702, } .into()]); }); @@ -2358,7 +2368,7 @@ fn sell_schedule_should_be_replanned_when_more_than_20_transaction_fee_left_for_ proceed_to_blocknumber(1, 500); let remainder = 20 * SELL_DCA_FEE_IN_NATIVE + 1; - let total_amount = ONE + SELL_DCA_FEE_IN_NATIVE + remainder; + let total_amount = 2 * (ONE + SELL_DCA_FEE_IN_NATIVE) + remainder; let amount_to_sell = ONE; let schedule = ScheduleBuilder::new() @@ -2380,14 +2390,15 @@ fn sell_schedule_should_be_replanned_when_more_than_20_transaction_fee_left_for_ assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act - set_to_blocknumber(501); + set_to_blocknumber(502); + set_to_blocknumber(602); //Assert let schedule_id = 0; expect_events(vec![DcaEvent::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 601, + block: 702, } .into()]); }); diff --git a/pallets/dca/src/tests/schedule.rs b/pallets/dca/src/tests/schedule.rs index b34c16738..89d11c71c 100644 --- a/pallets/dca/src/tests/schedule.rs +++ b/pallets/dca/src/tests/schedule.rs @@ -21,13 +21,11 @@ use crate::tests::mock::*; use crate::tests::{create_bounded_vec, ScheduleBuilder}; use crate::{Error, Event, Order}; use frame_support::{assert_noop, assert_ok}; -use frame_system::pallet_prelude::BlockNumberFor; use hydradx_traits::router::{PoolType, Trade}; use orml_traits::NamedMultiReservableCurrency; use pretty_assertions::assert_eq; use sp_runtime::DispatchError::BadOrigin; use std::ops::RangeInclusive; -use test_case::test_case; #[test] fn schedule_should_reserve_all_total_amount_as_named_reserve() { @@ -156,7 +154,7 @@ fn schedule_should_compound_named_reserve_for_multiple_schedules() { } #[test] -fn schedule_should_store_schedule_for_next_block_when_no_blocknumber_specified() { +fn schedule_should_store_schedule_with_2_blocks_delay_when_no_blocknumber_specified() { ExtBuilder::default() .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) .build() @@ -174,8 +172,8 @@ fn schedule_should_store_schedule_for_next_block_when_no_blocknumber_specified() assert_eq!(stored_schedule, ScheduleBuilder::new().build()); //Check if schedule ids are stored - let schedule_ids = DCA::schedule_ids_per_block(501); - assert!(!DCA::schedule_ids_per_block(501).is_empty()); + let schedule_ids = DCA::schedule_ids_per_block(502); + assert!(!DCA::schedule_ids_per_block(502).is_empty()); let expected_scheduled_ids_for_next_block = create_bounded_vec_with_schedule_ids(vec![schedule_id]); assert_eq!(schedule_ids, expected_scheduled_ids_for_next_block); @@ -209,7 +207,7 @@ fn schedule_should_work_when_multiple_schedules_stored() { assert!(DCA::schedules(schedule_id).is_some()); assert!(DCA::schedules(schedule_id_2).is_some()); - let scheduled_ids_for_next_block = DCA::schedule_ids_per_block(501); + let scheduled_ids_for_next_block = DCA::schedule_ids_per_block(502); let expected_scheduled_ids_for_next_block = create_bounded_vec_with_schedule_ids(vec![schedule_id, schedule_id_2]); @@ -344,7 +342,7 @@ fn schedule_should_emit_necessary_events_when_multiple_schedules_are_created() { Event::ExecutionPlanned { id: schedule_id, who: ALICE, - block: 501, + block: 502, } .into(), Event::Scheduled { @@ -473,39 +471,6 @@ fn buy_schedule_should_throw_error_when_total_budget_is_smaller_than_amount_in_p }); } -#[test] -fn buy_schedule_should_work_when_total_budget_is_equal_to_calculated_amount_in_plus_fee() { - ExtBuilder::default() - .with_endowed_accounts(vec![(ALICE, HDX, 100 * ONE)]) - .build() - .execute_with(|| { - //Arrange - let budget = CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY + BUY_DCA_FEE_IN_NATIVE; - - let schedule = ScheduleBuilder::new() - .with_total_amount(budget) - .with_period(ONE_HUNDRED_BLOCKS) - .with_order(Order::Buy { - asset_in: HDX, - asset_out: BTC, - amount_out: 10 * ONE, - max_amount_in: budget + BUY_DCA_FEE_IN_NATIVE, - route: create_bounded_vec(vec![Trade { - pool: PoolType::Omnipool, - asset_in: HDX, - asset_out: BTC, - }]), - }) - .build(); - - //Act - set_block_number(500); - - //Assert - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None),); - }); -} - #[test] fn schedule_should_fail_when_not_called_by_user() { ExtBuilder::default().build().execute_with(|| { @@ -517,26 +482,6 @@ fn schedule_should_fail_when_not_called_by_user() { }); } -#[test_case(1)] -#[test_case(499)] -#[test_case(500)] -fn schedule_should_fail_when_specified_next_block_is_not_greater_than_current_block(block: BlockNumberFor) { - ExtBuilder::default() - .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) - .build() - .execute_with(|| { - //Arrange - let schedule = ScheduleBuilder::new().build(); - set_block_number(500); - - //Act and assert - assert_noop!( - DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(block)), - Error::::BlockNumberIsNotInFuture - ); - }); -} - #[test] fn schedule_should_schedule_for_consequent_block_when_next_block_is_full() { ExtBuilder::default() @@ -548,19 +493,19 @@ fn schedule_should_schedule_for_consequent_block_when_next_block_is_full() { for _ in RangeInclusive::new(1, 20) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); } //Act let schedule = ScheduleBuilder::new().build(); let schedule_id = 20; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); //Assert - let actual_schedule_ids = DCA::schedule_ids_per_block(501); + let actual_schedule_ids = DCA::schedule_ids_per_block(1000); assert_eq!(20, actual_schedule_ids.len()); - assert_scheduled_ids!(502, vec![schedule_id]); + assert_scheduled_ids!(1005, vec![schedule_id]); }); } @@ -575,24 +520,24 @@ fn schedule_should_schedule_for_after_consequent_block_when_both_next_block_and_ for _ in RangeInclusive::new(1, 40) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); } //Act let schedule = ScheduleBuilder::new().build(); let schedule_id = 40; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); //Assert - let block = 501; + let block = 1000; let actual_schedule_ids = DCA::schedule_ids_per_block(block); assert_eq!(20, actual_schedule_ids.len()); - let actual_schedule_ids = DCA::schedule_ids_per_block(block + GENERATED_SEARCH_RADIUSES[0]); + let actual_schedule_ids = DCA::schedule_ids_per_block(block + DELAYS[0]); assert_eq!(20, actual_schedule_ids.len()); assert_scheduled_ids!( - block + GENERATED_SEARCH_RADIUSES[0] + GENERATED_SEARCH_RADIUSES[1], + block + DELAYS[0] + DELAYS[1], vec![schedule_id] ); }); @@ -609,13 +554,13 @@ fn schedule_should_fail_when_there_is_no_free_consquent_blocks() { for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); } //Check if all the blocks within radiuses are fully filled - let next_block = 501; + let next_block = 1000; let mut next_block_with_radius = next_block; - for radius in GENERATED_SEARCH_RADIUSES { + for radius in DELAYS { next_block_with_radius += radius; let actual_schedule_ids = DCA::schedule_ids_per_block(next_block_with_radius); assert_eq!(20, actual_schedule_ids.len()); @@ -624,7 +569,7 @@ fn schedule_should_fail_when_there_is_no_free_consquent_blocks() { //Act and assert let schedule = ScheduleBuilder::new().build(); assert_noop!( - DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None), + DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000)), Error::::NoFreeBlockFound ); }); @@ -792,14 +737,14 @@ fn schedule_should_fail_when_trade_amount_is_less_than_min_trading_limit() { } #[test] -fn sell_schedule_should_work_when_total_amount_is_equal_to_amount_in_plus_fee() { +fn sell_schedule_should_work_when_total_amount_is_equal_to_2times_amount_in_plus_fee() { ExtBuilder::default() .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) .build() .execute_with(|| { //Arrange let amount_in = ONE; - let total_amount = amount_in + SELL_DCA_FEE_IN_NATIVE; + let total_amount = 2 * (amount_in + SELL_DCA_FEE_IN_NATIVE); let schedule = ScheduleBuilder::new() .with_total_amount(total_amount) .with_order(Order::Sell { @@ -915,7 +860,7 @@ fn schedule_should_be_created_when_no_routes_specified() { } #[test] -fn thousands_of_dcas_should_be_schedules_on_a_specific_block_because_of_salt_added_to_block_search_randomness() { +fn thousands_of_dcas_can_be_scheduled_on_a_specific_block_because_of_salt_added_to_block_search_randomness() { ExtBuilder::default() .with_endowed_accounts(vec![(ALICE, HDX, 100000000000 * ONE)]) .build() diff --git a/pallets/dca/src/tests/terminate.rs b/pallets/dca/src/tests/terminate.rs index 7fb62ab3a..de29a0a97 100644 --- a/pallets/dca/src/tests/terminate.rs +++ b/pallets/dca/src/tests/terminate.rs @@ -49,31 +49,6 @@ fn terminate_should_remove_schedule_from_storage() { }); } -#[test] -fn terminate_should_terminate_schedule_planned_in_next_block_when_no_block_specified() { - ExtBuilder::default() - .with_endowed_accounts(vec![(ALICE, HDX, 10000 * ONE)]) - .build() - .execute_with(|| { - //Arrange - set_block_number(500); - let schedule = ScheduleBuilder::new().build(); - let schedule_id = 0; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); - - //Act - assert_ok!(DCA::terminate(RuntimeOrigin::root(), schedule_id, Option::None)); - - //Assert - expect_events(vec![Event::Terminated { - id: 0, - who: ALICE, - error: Error::::ManuallyTerminated.into(), - } - .into()]); - }); -} - #[test] fn terminate_should_unreserve_all_named_reserved() { ExtBuilder::default() @@ -206,7 +181,7 @@ fn terminate_should_pass_when_called_by_owner() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act and assert - assert_ok!(DCA::terminate(RuntimeOrigin::signed(ALICE), schedule_id, Some(501))); + assert_ok!(DCA::terminate(RuntimeOrigin::signed(ALICE), schedule_id, Some(502))); }); } @@ -260,7 +235,7 @@ fn terminate_should_pass_when_called_by_technical_origin() { assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::None)); //Act and assert - assert_ok!(DCA::terminate(RuntimeOrigin::root(), schedule_id, Some(501))); + assert_ok!(DCA::terminate(RuntimeOrigin::root(), schedule_id, Some(502))); }); } From 3cb280770f774de2db4a948bbfb6663c5453d4b9 Mon Sep 17 00:00:00 2001 From: dmoka Date: Fri, 19 Jul 2024 15:39:30 +0100 Subject: [PATCH 10/17] revert back to use StdRng for the randomness provider since we can mock out BumpChance easily --- .../stableswap/tests/invariants.txt | 7 -- pallets/dca/src/lib.rs | 69 ++++--------------- pallets/dca/src/tests/mock.rs | 34 +++------ pallets/dca/src/tests/on_initialize.rs | 11 +-- pallets/dca/src/tests/schedule.rs | 10 +-- 5 files changed, 30 insertions(+), 101 deletions(-) delete mode 100644 math/proptest-regressions/stableswap/tests/invariants.txt diff --git a/math/proptest-regressions/stableswap/tests/invariants.txt b/math/proptest-regressions/stableswap/tests/invariants.txt deleted file mode 100644 index 4988cffb0..000000000 --- a/math/proptest-regressions/stableswap/tests/invariants.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc 856506ae58747f1a2ab6af2afe18b3689666b7046416552f394b37600f915570 # shrinks to pool = [AssetReserve { amount: 10000000000, decimals: 6 }, AssetReserve { amount: 34164000000, decimals: 6 }, AssetReserve { amount: 556700554000000, decimals: 6 }, AssetReserve { amount: 709227553000000, decimals: 6 }], amount = 350, amp = 7326, (idx_in, idx_out) = (2, 0) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index 97f5533ac..47ee2ea9e 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -138,7 +138,7 @@ pub mod pallet { let mut schedule_ids: Vec = ScheduleIdsPerBlock::::take(current_blocknumber).to_vec(); - schedule_ids.sort_by_cached_key(|_| randomness_generator.gen_u32()); + schedule_ids.sort_by_cached_key(|_| randomness_generator.gen::()); for schedule_id in schedule_ids { Self::deposit_event(Event::ExecutionStarted { id: schedule_id, @@ -614,7 +614,7 @@ pub mod pallet { } impl Pallet { - fn get_randomness_generator(current_blocknumber: BlockNumberFor, salt: Option) -> Box { + fn get_randomness_generator(current_blocknumber: BlockNumberFor, salt: Option) -> StdRng { match T::RandomnessProvider::generator(salt) { Ok(generator) => generator, Err(err) => { @@ -623,12 +623,7 @@ impl Pallet { error: err, }); - let randomness_generator : RandomnessGenerator = RandomnessGenerator { - rng: rand::rngs::StdRng::seed_from_u64(0), - _marker: Default::default(), - }; - - Box::new(randomness_generator) + StdRng::seed_from_u64(0) } } } @@ -661,9 +656,9 @@ impl Pallet { weight_for_dca_execution: Weight, schedule_id: ScheduleId, schedule: &Schedule>, - randomness_generator: &mut Box, + randomness_generator: &mut StdRng, ) -> DispatchResult { - if Percent::from_percent(randomness_generator.gen_range_u8(0..100)) <= T::BumpChance::get() { + if Percent::from_percent(randomness_generator.gen_range(0..100)) <= T::BumpChance::get() { let next_block = current_blocknumber.saturating_add(1u32.into()); Self::plan_schedule_for_block(&schedule.owner, next_block, schedule_id, randomness_generator)?; return Err(Error::::Bumped.into()); @@ -783,7 +778,7 @@ impl Pallet { schedule: &Schedule>, current_blocknumber: BlockNumberFor, amounts: AmountInAndOut, - randomness_generator: &mut Box, + randomness_generator: &mut StdRng, ) -> DispatchResult { Self::deposit_event(Event::TradeExecuted { id: schedule_id, @@ -831,7 +826,7 @@ impl Pallet { schedule_id: ScheduleId, schedule: &Schedule>, current_blocknumber: BlockNumberFor, - randomness_generator: &mut Box, + randomness_generator: &mut StdRng, ) -> DispatchResult { let number_of_retries = Self::retries_on_error(schedule_id); @@ -1015,7 +1010,7 @@ impl Pallet { who: &T::AccountId, blocknumber: BlockNumberFor, schedule_id: ScheduleId, - randomness_generator: &mut Box, + randomness_generator: &mut StdRng, ) -> DispatchResult { let current_block_number = frame_system::Pallet::::current_block_number(); ensure!(blocknumber > current_block_number, Error::::BlockNumberIsNotInFuture); @@ -1039,7 +1034,7 @@ impl Pallet { fn find_next_free_block( blocknumber: BlockNumberFor, - randomness_generator: &mut Box, + randomness_generator: &mut StdRng, ) -> Result, DispatchError> { let mut next_execution_block = blocknumber; @@ -1052,7 +1047,7 @@ impl Pallet { let lower_bound = 2u32.saturating_pow(i); let upper_bound = 2u32.saturating_pow(i.saturating_add(1)).saturating_sub(1); - let delay_with = randomness_generator.gen_range_u32(lower_bound..=upper_bound); + let delay_with = randomness_generator.gen_range(lower_bound..=upper_bound); next_execution_block = next_execution_block.saturating_add(delay_with.into()); } @@ -1137,30 +1132,11 @@ impl Pallet { } pub trait RandomnessProvider { - fn generator(salt: Option) -> Result, DispatchError>; + fn generator(salt: Option) -> Result; } impl RandomnessProvider for Pallet { - fn generator(salt: Option) -> Result, DispatchError> { - let res = RandomnessGenerator::::new(salt)?; - - Ok(Box::new(res)) - } -} - -pub trait RandomNumberGenerator { - fn gen_u32(&mut self) -> u32; - fn gen_range_u8(&mut self, range: sp_std::ops::Range) -> u8; - fn gen_range_u32(&mut self, range: sp_std::ops::RangeInclusive) -> u32; -} - -pub struct RandomnessGenerator { - rng: StdRng, - _marker: sp_std::marker::PhantomData, -} - -impl RandomnessGenerator { - pub fn new(salt: Option) -> Result { + fn generator(salt: Option) -> Result { let hash_value = T::RelayChainBlockHashProvider::parent_hash().ok_or(Error::::NoParentHashFound)?; let hash_bytes = hash_value.as_fixed_bytes(); let mut seed_arr = [0u8; 8]; @@ -1172,25 +1148,6 @@ impl RandomnessGenerator { None => u64::from_le_bytes(seed_arr), }; - Ok(RandomnessGenerator { - rng: rand::rngs::StdRng::seed_from_u64(seed), - _marker: sp_std::marker::PhantomData, - }) - } -} - -impl RandomNumberGenerator for RandomnessGenerator { - fn gen_u32(&mut self) -> u32 { - self.rng.gen::() - } - - fn gen_range_u8(&mut self, range: sp_std::ops::Range) -> u8 - { - self.rng.gen_range(range) - } - - fn gen_range_u32(&mut self, range: sp_std::ops::RangeInclusive) -> u32 - { - self.rng.gen_range(range) + Ok(rand::rngs::StdRng::seed_from_u64(seed)) } } diff --git a/pallets/dca/src/tests/mock.rs b/pallets/dca/src/tests/mock.rs index a129c0756..0cdf383d6 100644 --- a/pallets/dca/src/tests/mock.rs +++ b/pallets/dca/src/tests/mock.rs @@ -16,7 +16,7 @@ // limitations under the License. use crate as dca; -use crate::{Config, Error, RandomnessGenerator, RandomnessProvider, RelayChainBlockHashProvider, RandomNumberGenerator}; +use crate::{Config, Error, RandomnessProvider, RelayChainBlockHashProvider}; use cumulus_primitives_core::relay_chain::Hash; use frame_support::traits::{Everything, Nothing}; use frame_support::weights::constants::ExtrinsicBaseWeight; @@ -68,8 +68,8 @@ pub const FORBIDDEN_ASSET: AssetId = 4; pub const REGISTERED_ASSET: AssetId = 1000; pub const ONE_HUNDRED_BLOCKS: BlockNumber = 100; -//Since we always return 5 in the MockRndGenerator, therefore the delay is the same -pub const DELAYS: [u64; 10] = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]; +//Since we always use the same parent hash in the tests, the generated radiuses are always the same +pub const GENERATED_SEARCH_RADIUSES: [u64; 10] = [1, 3, 6, 10, 28, 34, 114, 207, 504, 947]; pub const ONE: Balance = 1_000_000_000_000; @@ -646,43 +646,26 @@ parameter_types! { pub OmnipoolMaxAllowedPriceDifference: Permill = MAX_PRICE_DIFFERENCE.with(|v| *v.borrow()); pub MaxConfigurablePriceDifference: Permill = Permill::from_percent(20); pub MinimalPeriod: u32 = 5; - pub BumpChance: Percent = Percent::from_percent(17); + pub BumpChance: Percent = Percent::from_percent(0); pub NamedReserveId: NamedReserveIdentifier = *b"dcaorder"; pub MaxNumberOfRetriesOnError: u8 = 3; } +use rand::SeedableRng; pub struct RandomnessProviderMock {} impl RandomnessProvider for RandomnessProviderMock { - fn generator(salt: Option) -> Result, DispatchError> { + fn generator(salt: Option) -> Result { let use_prod_randomness = USE_PROD_RANDOMNESS.with(|v| *v.borrow()); if use_prod_randomness { - let gen = RandomnessGenerator::::new(salt).unwrap(); - Ok(Box::new(gen)) + DCA::generator(salt) } else { - Ok(Box::new(MockRndGenerator{})) + Ok(StdRng::seed_from_u64(0)) } } } -pub struct MockRndGenerator; - -impl RandomNumberGenerator for MockRndGenerator { - fn gen_u32(&mut self) -> u32 { - 1 - } - - fn gen_range_u8(&mut self, _range: Range) -> u8 { - 18 - } - - fn gen_range_u32(&mut self, _range: RangeInclusive) -> u32 { - 5 - } -} - - impl Config for Test { type RuntimeEvent = RuntimeEvent; type AssetId = AssetId; @@ -734,6 +717,7 @@ impl RelayChainBlockHashProvider for ParentHashGetterMock { use frame_support::traits::tokens::nonfungibles::{Create, Inspect, Mutate}; use frame_support::weights::{WeightToFeeCoefficients, WeightToFeePolynomial}; use frame_system::pallet_prelude::OriginFor; +use rand::rngs::StdRng; use hydra_dx_math::ema::EmaPrice; use hydra_dx_math::to_u128_wrapper; use hydra_dx_math::types::Ratio; diff --git a/pallets/dca/src/tests/on_initialize.rs b/pallets/dca/src/tests/on_initialize.rs index 370b8d48c..157caec94 100644 --- a/pallets/dca/src/tests/on_initialize.rs +++ b/pallets/dca/src/tests/on_initialize.rs @@ -2098,12 +2098,7 @@ fn dca_should_be_terminated_when_price_change_is_big_but_no_free_blocks_to_repla for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); - } - - for _ in RangeInclusive::new(1, 20) { - let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1055))); + assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1005)));//995 + 10 because 10 is the retry delay } //Act @@ -2157,7 +2152,7 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque assert_eq!(20, actual_schedule_ids.len()); //Check if all blocks found within radius are filled - for delay in DELAYS { + for delay in GENERATED_SEARCH_RADIUSES { execution_block += delay; let actual_schedule_ids = DCA::schedule_ids_per_block(execution_block); assert_eq!(20, actual_schedule_ids.len()); @@ -2167,7 +2162,7 @@ fn dca_should_be_executed_and_replanned_through_multiple_blocks_when_all_consque proceed_to_blocknumber(1000, 2000); //Assert - assert_number_of_executed_sell_trades!(2220); + assert_number_of_executed_sell_trades!(1740); //Assert if none of the schedule is terminated for schedule_id in RangeInclusive::new(0, 119) { diff --git a/pallets/dca/src/tests/schedule.rs b/pallets/dca/src/tests/schedule.rs index 89d11c71c..0cb058bf5 100644 --- a/pallets/dca/src/tests/schedule.rs +++ b/pallets/dca/src/tests/schedule.rs @@ -483,7 +483,7 @@ fn schedule_should_fail_when_not_called_by_user() { } #[test] -fn schedule_should_schedule_for_consequent_block_when_next_block_is_full() { +fn schedule_should_schedule_for_consequent_block_when_specified_block_is_full() { ExtBuilder::default() .with_endowed_accounts(vec![(ALICE, HDX, 1000000 * ONE)]) .build() @@ -505,7 +505,7 @@ fn schedule_should_schedule_for_consequent_block_when_next_block_is_full() { let actual_schedule_ids = DCA::schedule_ids_per_block(1000); assert_eq!(20, actual_schedule_ids.len()); - assert_scheduled_ids!(1005, vec![schedule_id]); + assert_scheduled_ids!(1001, vec![schedule_id]); }); } @@ -533,11 +533,11 @@ fn schedule_should_schedule_for_after_consequent_block_when_both_next_block_and_ let actual_schedule_ids = DCA::schedule_ids_per_block(block); assert_eq!(20, actual_schedule_ids.len()); - let actual_schedule_ids = DCA::schedule_ids_per_block(block + DELAYS[0]); + let actual_schedule_ids = DCA::schedule_ids_per_block(block + GENERATED_SEARCH_RADIUSES[0]); assert_eq!(20, actual_schedule_ids.len()); assert_scheduled_ids!( - block + DELAYS[0] + DELAYS[1], + block + GENERATED_SEARCH_RADIUSES[0] + GENERATED_SEARCH_RADIUSES[1], vec![schedule_id] ); }); @@ -560,7 +560,7 @@ fn schedule_should_fail_when_there_is_no_free_consquent_blocks() { //Check if all the blocks within radiuses are fully filled let next_block = 1000; let mut next_block_with_radius = next_block; - for radius in DELAYS { + for radius in GENERATED_SEARCH_RADIUSES { next_block_with_radius += radius; let actual_schedule_ids = DCA::schedule_ids_per_block(next_block_with_radius); assert_eq!(20, actual_schedule_ids.len()); From a46ff373426981f84390afb28a69b762a56ebf44 Mon Sep 17 00:00:00 2001 From: mrq Date: Fri, 19 Jul 2024 22:38:55 +0200 Subject: [PATCH 11/17] removed unused imports --- pallets/dca/src/lib.rs | 1 - pallets/dca/src/tests/mock.rs | 3 +-- runtime/hydradx/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index 47ee2ea9e..5d0216d68 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -85,7 +85,6 @@ use hydradx_traits::PriceOracle; use orml_traits::{arithmetic::CheckedAdd, MultiCurrency, NamedMultiReservableCurrency}; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; -use sp_std::boxed::Box; use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding; use sp_runtime::traits::CheckedMul; use sp_runtime::{ diff --git a/pallets/dca/src/tests/mock.rs b/pallets/dca/src/tests/mock.rs index 0cdf383d6..376724cd5 100644 --- a/pallets/dca/src/tests/mock.rs +++ b/pallets/dca/src/tests/mock.rs @@ -46,7 +46,6 @@ use sp_runtime::traits::Zero; use sp_runtime::{DispatchResult, FixedU128}; use std::cell::RefCell; use std::collections::HashMap; -use std::ops::{Range, RangeInclusive}; type Block = frame_system::mocking::MockBlock; @@ -717,13 +716,13 @@ impl RelayChainBlockHashProvider for ParentHashGetterMock { use frame_support::traits::tokens::nonfungibles::{Create, Inspect, Mutate}; use frame_support::weights::{WeightToFeeCoefficients, WeightToFeePolynomial}; use frame_system::pallet_prelude::OriginFor; -use rand::rngs::StdRng; use hydra_dx_math::ema::EmaPrice; use hydra_dx_math::to_u128_wrapper; use hydra_dx_math::types::Ratio; use hydradx_traits::router::{ExecutorError, PoolType, RefundEdCalculator, RouteProvider, Trade, TradeExecution}; use pallet_currencies::fungibles::FungibleCurrencies; use pallet_omnipool::traits::ExternalPriceProvider; +use rand::rngs::StdRng; use smallvec::smallvec; pub struct DummyNFT; diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index b4e698756..0543cc488 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 246, + spec_version: 247, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 072307f64873730bffc5cd185e48b84e787839be Mon Sep 17 00:00:00 2001 From: mrq Date: Fri, 19 Jul 2024 22:39:17 +0200 Subject: [PATCH 12/17] versions bumped --- Cargo.lock | 14 ++++----- integration-tests/Cargo.toml | 14 ++++----- pallets/dca/Cargo.toml | 2 +- pallets/democracy/Cargo.toml | 60 ++++++++++++++++++------------------ runtime/hydradx/Cargo.toml | 10 +++--- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9b700c10..cc66c964b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "246.0.0" +version = "247.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -4989,7 +4989,7 @@ dependencies = [ "pallet-collective", "pallet-currencies", "pallet-dca", - "pallet-democracy 4.2.1", + "pallet-democracy 4.2.2", "pallet-duster", "pallet-dynamic-evm-fee", "pallet-dynamic-fees", @@ -7938,7 +7938,7 @@ dependencies = [ [[package]] name = "pallet-dca" -version = "1.4.9" +version = "1.5.0" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -7976,7 +7976,7 @@ dependencies = [ [[package]] name = "pallet-democracy" -version = "4.2.1" +version = "4.2.2" dependencies = [ "frame-benchmarking", "frame-support", @@ -9071,7 +9071,7 @@ dependencies = [ "orml-tokens", "orml-traits", "pallet-balances", - "pallet-democracy 4.2.1", + "pallet-democracy 4.2.2", "pallet-uniques", "parity-scale-codec", "pretty_assertions", @@ -11929,7 +11929,7 @@ dependencies = [ [[package]] name = "runtime-integration-tests" -version = "1.22.5" +version = "1.23.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -11971,7 +11971,7 @@ dependencies = [ "pallet-collective", "pallet-currencies", "pallet-dca", - "pallet-democracy 4.2.1", + "pallet-democracy 4.2.2", "pallet-duster", "pallet-dynamic-evm-fee", "pallet-dynamic-fees", diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 2524e59f9..00ecc5b21 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.22.5" +version = "1.23.0" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" @@ -32,14 +32,14 @@ warehouse-liquidity-mining = { workspace = true } pallet-otc = { workspace = true } pallet-otc-settlements = { workspace = true } pallet-relaychain-info = { workspace = true } -pallet-route-executor = { workspace = true} -pallet-dca = { workspace = true} +pallet-route-executor = { workspace = true } +pallet-dca = { workspace = true } pallet-dynamic-fees = { workspace = true } pallet-dynamic-evm-fee = { workspace = true } -pallet-staking = { workspace = true} -pallet-lbp = { workspace = true} -pallet-xyk = { workspace = true} -pallet-evm-accounts = { workspace = true} +pallet-staking = { workspace = true } +pallet-lbp = { workspace = true } +pallet-xyk = { workspace = true } +pallet-evm-accounts = { workspace = true } pallet-treasury = { workspace = true } pallet-democracy = { workspace = true } diff --git a/pallets/dca/Cargo.toml b/pallets/dca/Cargo.toml index 20a79a7c5..46d04cf67 100644 --- a/pallets/dca/Cargo.toml +++ b/pallets/dca/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-dca' -version = "1.4.9" +version = "1.5.0" description = 'A pallet to manage DCA scheduling' authors = ['GalacticCouncil'] edition = '2021' diff --git a/pallets/democracy/Cargo.toml b/pallets/democracy/Cargo.toml index f3304d7cc..81af44306 100644 --- a/pallets/democracy/Cargo.toml +++ b/pallets/democracy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-democracy" -version = "4.2.1" +version = "4.2.2" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,13 +14,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ - "derive", + "derive", ] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0.188", features = ["derive"], optional = true } log = { workspace = true } -frame-benchmarking = { workspace = true, optional = true} +frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } sp-io = { workspace = true } @@ -34,36 +34,36 @@ pallet-scheduler = { workspace = true } pallet-preimage = { workspace = true } [features] -default = [ "std" ] +default = ["std"] std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "pallet-preimage/std", - "pallet-scheduler/std", - "scale-info/std", - "serde", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-preimage/std", + "pallet-scheduler/std", + "scale-info/std", + "serde", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-preimage/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-balances/try-runtime", - "pallet-preimage/try-runtime", - "pallet-scheduler/try-runtime", - "sp-runtime/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-preimage/try-runtime", + "pallet-scheduler/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index 5db73f849..e26d69500 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "246.0.0" +version = "247.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" @@ -62,7 +62,7 @@ pallet-multisig = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-uniques = { workspace = true } -pallet-message-queue= { workspace = true } +pallet-message-queue = { workspace = true } pallet-state-trie-migration = { workspace = true } # Warehouse dependencies @@ -116,7 +116,7 @@ pallet-xcm = { workspace = true } polkadot-xcm = { workspace = true } xcm-executor = { workspace = true } xcm-builder = { workspace = true } -polkadot-runtime-common= { workspace = true } +polkadot-runtime-common = { workspace = true } # Substrate dependencies frame-benchmarking = { workspace = true, optional = true } @@ -143,7 +143,7 @@ sp-transaction-pool = { workspace = true } sp-version = { workspace = true } sp-trie = { workspace = true } sp-io = { workspace = true } -primitive-types = { workspace = true } +primitive-types = { workspace = true } # Frontier fp-rpc = { workspace = true } @@ -324,7 +324,7 @@ std = [ "polkadot-runtime-common/std", "pallet-state-trie-migration/std", ] -try-runtime= [ +try-runtime = [ "frame-try-runtime", "frame-executive/try-runtime", "frame-system/try-runtime", From 85d6170e54b22c66b13990d289407263e9f6c9bf Mon Sep 17 00:00:00 2001 From: mrq Date: Fri, 19 Jul 2024 22:48:11 +0200 Subject: [PATCH 13/17] fmt --- pallets/dca/src/tests/on_initialize.rs | 14 +++++++++--- pallets/dca/src/tests/schedule.rs | 30 +++++++++++++++++++++----- pallets/democracy/src/lib.rs | 2 +- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/pallets/dca/src/tests/on_initialize.rs b/pallets/dca/src/tests/on_initialize.rs index 157caec94..d04568d6b 100644 --- a/pallets/dca/src/tests/on_initialize.rs +++ b/pallets/dca/src/tests/on_initialize.rs @@ -650,7 +650,7 @@ fn full_buy_dca_should_be_completed_when_some_successful_dca_execution_happened_ assert_eq!(0, Currencies::reserved_balance(HDX, &ALICE)); assert_number_of_executed_buy_trades!(2); - assert_balance!(ALICE, BTC, 2*CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY); + assert_balance!(ALICE, BTC, 2 * CALCULATED_AMOUNT_IN_FOR_OMNIPOOL_BUY); let schedule_id = 0; assert_that_dca_is_completed(ALICE, schedule_id); @@ -2045,7 +2045,11 @@ fn dca_should_be_terminated_when_dca_cannot_be_planned_due_to_not_free_blocks() for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); } //Act @@ -2098,7 +2102,11 @@ fn dca_should_be_terminated_when_price_change_is_big_but_no_free_blocks_to_repla for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1005)));//995 + 10 because 10 is the retry delay + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1005) + )); //995 + 10 because 10 is the retry delay } //Act diff --git a/pallets/dca/src/tests/schedule.rs b/pallets/dca/src/tests/schedule.rs index 0cb058bf5..921439575 100644 --- a/pallets/dca/src/tests/schedule.rs +++ b/pallets/dca/src/tests/schedule.rs @@ -493,13 +493,21 @@ fn schedule_should_schedule_for_consequent_block_when_specified_block_is_full() for _ in RangeInclusive::new(1, 20) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); } //Act let schedule = ScheduleBuilder::new().build(); let schedule_id = 20; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); //Assert let actual_schedule_ids = DCA::schedule_ids_per_block(1000); @@ -520,13 +528,21 @@ fn schedule_should_schedule_for_after_consequent_block_when_both_next_block_and_ for _ in RangeInclusive::new(1, 40) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); } //Act let schedule = ScheduleBuilder::new().build(); let schedule_id = 40; - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); //Assert let block = 1000; @@ -554,7 +570,11 @@ fn schedule_should_fail_when_there_is_no_free_consquent_blocks() { for _ in RangeInclusive::new(1, 220) { let schedule = ScheduleBuilder::new().build(); - assert_ok!(DCA::schedule(RuntimeOrigin::signed(ALICE), schedule, Option::Some(1000))); + assert_ok!(DCA::schedule( + RuntimeOrigin::signed(ALICE), + schedule, + Option::Some(1000) + )); } //Check if all the blocks within radiuses are fully filled diff --git a/pallets/democracy/src/lib.rs b/pallets/democracy/src/lib.rs index 67cf7a58d..c8f1797d2 100644 --- a/pallets/democracy/src/lib.rs +++ b/pallets/democracy/src/lib.rs @@ -181,13 +181,13 @@ pub mod weights; use crate::traits::DemocracyHooks; pub use conviction::Conviction; pub use pallet::*; +use sp_std::vec; pub use types::{ Delegations, MetadataOwner, PropIndex, ReferendumIndex, ReferendumInfo, ReferendumStatus, Tally, UnvoteScope, }; pub use vote::{AccountVote, Vote, Voting}; pub use vote_threshold::{Approved, VoteThreshold}; pub use weights::WeightInfo; -use sp_std::vec; #[cfg(test)] mod tests; From 22abd013a2a517c3d6cc6f630fa1bb296c7817a6 Mon Sep 17 00:00:00 2001 From: mrq Date: Fri, 19 Jul 2024 22:58:16 +0200 Subject: [PATCH 14/17] runtime 249 --- Cargo.lock | 2 +- runtime/hydradx/Cargo.toml | 2 +- runtime/hydradx/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7bbc42cc..f6be7d76e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "248.0.0" +version = "249.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index fceb7401a..eeafc0f93 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "248.0.0" +version = "249.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 2e34909ec..a1c2b9bf0 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 248, + spec_version: 249, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From a1e9a0772e94a871b44b0b96f0d2c4097570d00c Mon Sep 17 00:00:00 2001 From: mrq Date: Sat, 20 Jul 2024 04:35:25 +0200 Subject: [PATCH 15/17] bechmarks params adjusted --- runtime/hydradx/src/benchmarking/dca.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/runtime/hydradx/src/benchmarking/dca.rs b/runtime/hydradx/src/benchmarking/dca.rs index 9f5153d84..f51914458 100644 --- a/runtime/hydradx/src/benchmarking/dca.rs +++ b/runtime/hydradx/src/benchmarking/dca.rs @@ -65,7 +65,7 @@ fn schedule_fake( ) -> Schedule { let schedule1: Schedule = Schedule { owner, - period: 3u32, + period: 5u32, total_amount: 1100 * ONE, max_retries: None, stability_threshold: None, @@ -97,7 +97,7 @@ fn schedule_buy_fake( ) -> Schedule { let schedule1: Schedule = Schedule { owner, - period: 3u32, + period: 5u32, total_amount: 2000 * ONE, max_retries: None, stability_threshold: None, @@ -125,7 +125,7 @@ fn schedule_sell_fake( ) -> Schedule { let schedule1: Schedule = Schedule { owner, - period: 3u32, + period: 5u32, total_amount: 2000 * ONE, max_retries: None, stability_threshold: None, @@ -197,7 +197,7 @@ runtime_benchmarks! { fund_treasury()?; let schedule1 = schedule_buy_fake(seller.clone(), HDX, DAI, amount_buy); - let execution_block = 1001u32; + let execution_block = 1005u32; assert_ok!(DCA::schedule(RawOrigin::Signed(seller.clone()).into(), schedule1.clone(), Option::Some(execution_block))); @@ -211,7 +211,7 @@ runtime_benchmarks! { //Make sure that we have other schedules planned in the block where the benchmark schedule is planned, leading to worst case //We leave only one slot - let schedule_period = 3; + let schedule_period = 5; let next_block_to_replan = execution_block + schedule_period; let number_of_all_schedules = MaxSchedulesPerBlock::get() + MaxSchedulesPerBlock::get() * RETRY_TO_SEARCH_FOR_FREE_BLOCK - 1; for i in 0..number_of_all_schedules { @@ -239,7 +239,7 @@ runtime_benchmarks! { fund_treasury()?; //Fund treasury with some HDX to prevent BelowMinimum issue due to low fee let schedule1 = schedule_sell_fake(seller.clone(), HDX, DAI, amount_sell); - let execution_block = 1001u32; + let execution_block = 1005u32; assert_ok!(DCA::schedule(RawOrigin::Signed(seller.clone()).into(), schedule1.clone(), Option::Some(execution_block))); @@ -253,7 +253,7 @@ runtime_benchmarks! { //Make sure that we have other schedules planned in the block where the benchmark schedule is planned, leading to worst case //We leave only one slot - let schedule_period = 3; + let schedule_period = 5; let next_block_to_replan = execution_block + schedule_period; let number_of_all_schedules = MaxSchedulesPerBlock::get() + MaxSchedulesPerBlock::get() * RETRY_TO_SEARCH_FOR_FREE_BLOCK - 1; for i in 0..number_of_all_schedules { @@ -345,7 +345,7 @@ runtime_benchmarks! { let schedule1: Schedule = Schedule { owner:caller.clone() , - period: 3u32, + period: 5u32, total_amount: 1100 * ONE, max_retries: None, stability_threshold: None, @@ -363,7 +363,7 @@ runtime_benchmarks! { }, }; - let execution_block = 100u32; + let execution_block = 105u32; //We fill blocks with schedules leaving only one place let schedule_2 = schedule_fake(caller.clone(), HDX, DAI, amount_sell); From 9bf21a6d6db97513f7b4ccba89a204fc73cff636 Mon Sep 17 00:00:00 2001 From: dmoka Date: Sat, 20 Jul 2024 09:32:17 +0100 Subject: [PATCH 16/17] fix terminate benchmark test --- runtime/hydradx/src/benchmarking/dca.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/hydradx/src/benchmarking/dca.rs b/runtime/hydradx/src/benchmarking/dca.rs index f51914458..02af52cc6 100644 --- a/runtime/hydradx/src/benchmarking/dca.rs +++ b/runtime/hydradx/src/benchmarking/dca.rs @@ -397,7 +397,7 @@ runtime_benchmarks! { let execution_block = 100u32; assert_ok!(DCA::schedule(RawOrigin::Signed(caller).into(), schedule1, Option::Some(execution_block))); - }: _(RawOrigin::Root, schedule_id, None) + }: _(RawOrigin::Root, schedule_id, Some(105)) verify { assert!(>::get::(schedule_id).is_none()); } From d6d219807f69a6e5c288a0b1ea16094ea8da876d Mon Sep 17 00:00:00 2001 From: mrq Date: Sat, 20 Jul 2024 11:14:44 +0200 Subject: [PATCH 17/17] speed up polkadot-sdk fetch --- Makefile | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index fed60e662..07c8c5003 100644 --- a/Makefile +++ b/Makefile @@ -1,59 +1,61 @@ +cargo := cargo --config net.git-fetch-with-cli=true + .PHONY: build build: - cargo build --release --locked + $(cargo) build --release --locked .PHONY: build-release build-release: - cargo build --release --locked --features metadata-hash + $(cargo) build --release --locked --features metadata-hash .PHONY: check check: - cargo check --release + $(cargo) check --release .PHONY: build-benchmarks build-benchmarks: - cargo build --release --features runtime-benchmarks + $(cargo) build --release --features runtime-benchmarks .PHONY: test test: - cargo test --locked + $(cargo) test --locked .PHONY: test-release test-release: - cargo test --release --locked + $(cargo) test --release --locked .PHONY: test-benchmarks test-benchmarks: - cargo test --release --features runtime-benchmarks + $(cargo) test --release --features runtime-benchmarks .PHONY: coverage coverage: - cargo tarpaulin --avoid-cfg-tarpaulin --all-features --workspace --locked --exclude-files node/* --exclude-files runtime/* --exclude-files infrastructure/* --exclude-files utils/* --exclude-files **/weights.rs --ignore-tests -o Xml -o lcov --timeout 120 + $(cargo) tarpaulin --avoid-cfg-tarpaulin --all-features --workspace --locked --exclude-files node/* --exclude-files runtime/* --exclude-files infrastructure/* --exclude-files utils/* --exclude-files **/weights.rs --ignore-tests -o Xml -o lcov --timeout 120 .PHONY: clippy clippy: - cargo clippy --release --locked --all-targets -- -D warnings -A deprecated + $(cargo) clippy --release --locked --all-targets -- -D warnings -A deprecated .PHONY: clippy-all clippy-all: - cargo clippy --release --locked --all-targets --all-features -- -D warnings -A deprecated + $(cargo) clippy --release --locked --all-targets --all-features -- -D warnings -A deprecated .PHONY: format format: - cargo fmt + $(cargo) fmt .PHONY: try-runtime try-runtime: - cargo build --release --features try-runtime + $(cargo) build --release --features try-runtime try-runtime --runtime ./target/release/wbuild/hydradx-runtime/hydradx_runtime.wasm on-runtime-upgrade --checks all live --uri wss://rpc.hydradx.cloud:443 .PHONY: build-docs build-docs: - cargo doc --release --target-dir ./HydraDX-dev-docs --no-deps + $(cargo) doc --release --target-dir ./HydraDX-dev-docs --no-deps .PHONY: clean clean: - cargo clean + $(cargo) clean .PHONY: docker docker: