diff --git a/asset-registry/Cargo.toml b/asset-registry/Cargo.toml index 66ec45fd7..bc7cdb061 100644 --- a/asset-registry/Cargo.toml +++ b/asset-registry/Cargo.toml @@ -78,6 +78,7 @@ std = [ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "orml-tokens/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/asset-registry/src/mock/para.rs b/asset-registry/src/mock/para.rs index 618159439..ab64c8c4f 100644 --- a/asset-registry/src/mock/para.rs +++ b/asset-registry/src/mock/para.rs @@ -77,6 +77,8 @@ impl orml_tokens::Config for Runtime { type MaxReserves = (); type MaxLocks = ConstU32<50>; type DustRemovalWhitelist = Nothing; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } #[derive(scale_info::TypeInfo, Encode, Decode, Clone, Eq, PartialEq, Debug, MaxEncodedLen, DecodeWithMemTracking)] diff --git a/currencies/Cargo.toml b/currencies/Cargo.toml index 7208e5363..f76c127c1 100644 --- a/currencies/Cargo.toml +++ b/currencies/Cargo.toml @@ -25,7 +25,7 @@ orml-utilities = { path = "../utilities", version = "1.5.0", default-features = pallet-balances = { workspace = true, features = ["std"] } sp-core = { workspace = true, features = ["std"] } -orml_tokens = { package = "orml-tokens", path = "../tokens" } +orml-tokens = { path = "../tokens", features = ["std"] } [features] default = [ "std" ] @@ -41,6 +41,12 @@ std = [ "sp-runtime/std", "sp-std/std", ] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "orml-tokens/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/currencies/src/mock.rs b/currencies/src/mock.rs index f08ca1b41..9a8a38dbe 100644 --- a/currencies/src/mock.rs +++ b/currencies/src/mock.rs @@ -85,6 +85,8 @@ impl orml_tokens::Config for Runtime { type MaxReserves = ConstU32<100_000>; type ReserveIdentifier = ReserveIdentifier; type DustRemovalWhitelist = Nothing; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } pub const NATIVE_CURRENCY_ID: CurrencyId = 1; diff --git a/oracle/src/benchmarking.rs b/oracle/src/benchmarking.rs index 591016638..46c173f55 100644 --- a/oracle/src/benchmarking.rs +++ b/oracle/src/benchmarking.rs @@ -1,10 +1,25 @@ pub use crate::*; -use frame_benchmarking::v2::{impl_test_function, instance_benchmarks, whitelisted_caller}; - +use frame_benchmarking::v2::*; use frame_support::assert_ok; use frame_system::{Pallet as System, RawOrigin}; +/// Helper trait for benchmarking. +pub trait BenchmarkHelper> { + /// Returns a list of `(oracle_key, oracle_value)` pairs to be used for + /// benchmarking. + /// + /// NOTE: User should ensure to at least submit two values, otherwise the + /// benchmark linear analysis might fail. + fn get_currency_id_value_pairs() -> BoundedVec<(OracleKey, OracleValue), L>; +} + +impl> BenchmarkHelper for () { + fn get_currency_id_value_pairs() -> BoundedVec<(OracleKey, OracleValue), L> { + BoundedVec::default() + } +} + #[instance_benchmarks] mod benchmarks { use super::*; diff --git a/oracle/src/lib.rs b/oracle/src/lib.rs index 869829434..9570da6c5 100644 --- a/oracle/src/lib.rs +++ b/oracle/src/lib.rs @@ -43,34 +43,18 @@ use sp_std::{prelude::*, vec}; pub use crate::default_combine_data::DefaultCombineData; #[cfg(feature = "runtime-benchmarks")] -pub mod benchmarking; +mod benchmarking; mod default_combine_data; mod mock; mod tests; mod weights; +#[cfg(feature = "runtime-benchmarks")] +pub use benchmarking::BenchmarkHelper; pub use module::*; pub use weights::WeightInfo; -#[cfg(feature = "runtime-benchmarks")] -/// Helper trait for benchmarking. -pub trait BenchmarkHelper> { - /// Returns a list of `(oracle_key, oracle_value)` pairs to be used for - /// benchmarking. - /// - /// NOTE: User should ensure to at least submit two values, otherwise the - /// benchmark linear analysis might fail. - fn get_currency_id_value_pairs() -> BoundedVec<(OracleKey, OracleValue), L>; -} - -#[cfg(feature = "runtime-benchmarks")] -impl> BenchmarkHelper for () { - fn get_currency_id_value_pairs() -> BoundedVec<(OracleKey, OracleValue), L> { - BoundedVec::default() - } -} - #[frame_support::pallet] pub mod module { use super::*; diff --git a/payments/Cargo.toml b/payments/Cargo.toml index 383278fc0..e52e77c6d 100644 --- a/payments/Cargo.toml +++ b/payments/Cargo.toml @@ -26,7 +26,7 @@ orml-traits = {path = "../traits", version = "1.5.0", default-features = false } sp-core = { workspace = true } sp-io = { workspace = true } -orml-tokens = { path = "../tokens" } +orml-tokens = { path = "../tokens", features = ["std"] } [features] default = [ 'std' ] @@ -41,6 +41,12 @@ std = [ 'sp-runtime/std', 'sp-std/std', ] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "orml-tokens/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/payments/src/mock.rs b/payments/src/mock.rs index 956568cee..f96d5f148 100644 --- a/payments/src/mock.rs +++ b/payments/src/mock.rs @@ -74,6 +74,8 @@ impl orml_tokens::Config for Test { type DustRemovalWhitelist = MockDustRemovalWhitelist; type MaxReserves = ConstU32<2>; type ReserveIdentifier = ReserveIdentifier; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } pub struct MockDisputeResolver; diff --git a/tokens/Cargo.toml b/tokens/Cargo.toml index dc7ab3deb..eaafa9ecd 100644 --- a/tokens/Cargo.toml +++ b/tokens/Cargo.toml @@ -13,6 +13,7 @@ log = { workspace = true } scale-info = { workspace = true } serde = { workspace = true, optional = true } +frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } sp-arithmetic = { workspace = true } @@ -31,6 +32,7 @@ sp-staking = { workspace = true, features = ["std"] } [features] default = [ "std" ] std = [ + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", @@ -43,8 +45,10 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/tokens/src/benchmarking.rs b/tokens/src/benchmarking.rs new file mode 100644 index 000000000..83856b15e --- /dev/null +++ b/tokens/src/benchmarking.rs @@ -0,0 +1,139 @@ +pub use crate::*; + +use frame_benchmarking::v2::*; +use frame_support::assert_ok; +use frame_system::RawOrigin; +use sp_runtime::traits::SaturatedConversion; + +/// Helper trait for benchmarking. +pub trait BenchmarkHelper { + /// Returns a currency id and amount to be used in benchmarking. + fn get_currency_id_and_amount() -> Option<(CurrencyId, Balance)>; +} + +impl BenchmarkHelper for () { + fn get_currency_id_and_amount() -> Option<(CurrencyId, Balance)> { + None + } +} + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn transfer() { + let from: T::AccountId = account("from", 0, 0); + + let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); + + assert_ok!( as MultiCurrencyExtended<_>>::update_balance( + currency_id, + &from, + amount.saturated_into() + )); + + let to: T::AccountId = account("to", 0, 0); + let to_lookup = ::Lookup::unlookup(to.clone()); + + #[extrinsic_call] + _(RawOrigin::Signed(from), to_lookup, currency_id, amount); + + assert_eq!(Pallet::::total_balance(currency_id, &to), amount); + } + + #[benchmark] + fn transfer_all() { + let from: T::AccountId = account("from", 0, 0); + + let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); + + assert_ok!( as MultiCurrencyExtended<_>>::update_balance( + currency_id, + &from, + amount.saturated_into() + )); + + let to: T::AccountId = account("to", 0, 0); + let to_lookup = ::Lookup::unlookup(to.clone()); + + #[extrinsic_call] + _(RawOrigin::Signed(from.clone()), to_lookup, currency_id, false); + + assert_eq!( + as MultiCurrency<_>>::total_balance(currency_id, &from), + 0u32.into() + ); + } + + #[benchmark] + fn transfer_keep_alive() { + let from: T::AccountId = account("from", 0, 0); + + let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); + + assert_ok!( as MultiCurrencyExtended<_>>::update_balance( + currency_id, + &from, + amount.saturating_mul(2u32.into()).saturated_into() + )); + + let to: T::AccountId = account("to", 0, 0); + let to_lookup = ::Lookup::unlookup(to.clone()); + + #[extrinsic_call] + _(RawOrigin::Signed(from), to_lookup, currency_id, amount); + + assert_eq!( + as MultiCurrency<_>>::total_balance(currency_id, &to), + amount + ); + } + + #[benchmark] + fn force_transfer() { + let from: T::AccountId = account("from", 0, 0); + let from_lookup = ::Lookup::unlookup(from.clone()); + + let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); + + assert_ok!( as MultiCurrencyExtended<_>>::update_balance( + currency_id, + &from, + amount.saturated_into() + )); + + let to: T::AccountId = account("to", 0, 0); + let to_lookup = ::Lookup::unlookup(to.clone()); + + #[extrinsic_call] + _(RawOrigin::Root, from_lookup, to_lookup, currency_id, amount); + + assert_eq!( + as MultiCurrency<_>>::total_balance(currency_id, &to), + amount + ); + } + + #[benchmark] + fn set_balance() { + let who: T::AccountId = account("who", 0, 0); + let who_lookup = ::Lookup::unlookup(who.clone()); + + let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); + + #[extrinsic_call] + _(RawOrigin::Root, who_lookup, currency_id, amount, amount); + + assert_eq!( + as MultiCurrency<_>>::total_balance(currency_id, &who), + amount.saturating_mul(2u32.into()) + ); + } + + impl_benchmark_test_suite! { + Pallet, + crate::mock::ExtBuilder::default().build(), + crate::mock::Runtime, + } +} diff --git a/tokens/src/lib.rs b/tokens/src/lib.rs index 9f6a03ee3..2e29df8a4 100644 --- a/tokens/src/lib.rs +++ b/tokens/src/lib.rs @@ -71,6 +71,8 @@ use orml_traits::{ MultiReservableCurrency, NamedMultiReservableCurrency, }; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; mod imbalances; mod impls; mod mock; @@ -82,6 +84,8 @@ mod tests_multicurrency; mod weights; +#[cfg(feature = "runtime-benchmarks")] +pub use benchmarking::BenchmarkHelper; pub use impls::*; pub use weights::WeightInfo; @@ -226,6 +230,10 @@ pub mod module { // The whitelist of accounts that will not be reaped even if its total // is zero or below ED. type DustRemovalWhitelist: Contains; + + /// The benchmarks need a way to provide currency id. + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper: BenchmarkHelper; } #[pallet::error] diff --git a/tokens/src/mock.rs b/tokens/src/mock.rs index 5e1c62392..7a204a004 100644 --- a/tokens/src/mock.rs +++ b/tokens/src/mock.rs @@ -375,6 +375,15 @@ where type OnKilledTokenAccount = TrackKilledAccounts; } +#[cfg(feature = "runtime-benchmarks")] +pub struct MockBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for MockBenchmarkHelper { + fn get_currency_id_and_amount() -> Option<(CurrencyId, Balance)> { + Some((DOT, 1000)) + } +} + impl Config for Runtime { type Balance = Balance; type Amount = i64; @@ -386,6 +395,8 @@ impl Config for Runtime { type MaxReserves = ConstU32<2>; type ReserveIdentifier = ReserveIdentifier; type DustRemovalWhitelist = MockDustRemovalWhitelist; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = MockBenchmarkHelper; } pub type TreasuryCurrencyAdapter = ::Currency; diff --git a/xtokens/Cargo.toml b/xtokens/Cargo.toml index 3d024bfb7..d4ea8402b 100644 --- a/xtokens/Cargo.toml +++ b/xtokens/Cargo.toml @@ -75,6 +75,7 @@ std = [ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "orml-tokens/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 4e4e336cd..6946b950f 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -77,6 +77,8 @@ impl orml_tokens::Config for Runtime { type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; type DustRemovalWhitelist = Everything; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! { diff --git a/xtokens/src/mock/para_relative_view.rs b/xtokens/src/mock/para_relative_view.rs index 1a1a7a8c2..33ba7771d 100644 --- a/xtokens/src/mock/para_relative_view.rs +++ b/xtokens/src/mock/para_relative_view.rs @@ -74,6 +74,8 @@ impl orml_tokens::Config for Runtime { type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; type DustRemovalWhitelist = Everything; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! { diff --git a/xtokens/src/mock/para_teleport.rs b/xtokens/src/mock/para_teleport.rs index 7ee19feaa..9ebfd5e68 100644 --- a/xtokens/src/mock/para_teleport.rs +++ b/xtokens/src/mock/para_teleport.rs @@ -74,6 +74,8 @@ impl orml_tokens::Config for Runtime { type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; type DustRemovalWhitelist = Everything; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! {