diff --git a/Cargo.lock b/Cargo.lock index bdad2c770c..fa84c23dbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6390,6 +6390,7 @@ dependencies = [ "pallet-moonbeam-orbiters", "pallet-multisig", "pallet-parachain-staking", + "pallet-parameters", "pallet-precompile-benchmarks", "pallet-preimage", "pallet-proxy", @@ -6985,6 +6986,7 @@ dependencies = [ "pallet-moonbeam-orbiters", "pallet-multisig", "pallet-parachain-staking", + "pallet-parameters", "pallet-precompile-benchmarks", "pallet-preimage", "pallet-proxy", diff --git a/Cargo.toml b/Cargo.toml index 0578bfc1bf..c3a8bea3d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,6 +148,7 @@ pallet-identity = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", pallet-message-queue = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } pallet-multisig = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } pallet-preimage = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } +pallet-parameters = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } pallet-proxy = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } pallet-referenda = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } pallet-root-testing = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index b94bbbc4ca..8a9ff1de6b 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -44,6 +44,7 @@ pallet-identity = { workspace = true } pallet-moonbeam-orbiters = { workspace = true } pallet-multisig = { workspace = true } pallet-preimage = { workspace = true } +pallet-parameters = { workspace = true } pallet-proxy = { workspace = true } pallet-referenda = { workspace = true } pallet-scheduler = { workspace = true } @@ -100,6 +101,7 @@ std = [ "pallet-evm/std", "pallet-migrations/std", "pallet-parachain-staking/std", + "pallet-parameters/std", "pallet-randomness/std", "pallet-referenda/std", "pallet-scheduler/std", @@ -139,6 +141,7 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-parachain-staking/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", + "pallet-parameters/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-randomness/runtime-benchmarks", "pallet-referenda/runtime-benchmarks", diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 38912cb7d4..d9aa574eaa 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -1124,6 +1124,13 @@ macro_rules! impl_runtime_apis_plus_common { hex_literal::hex!( "0d715f2646c8f85767b5d2764bb27826" "04a74d81251e398fd8a0a4d55023bb3f") .to_vec().into(), + // Parameters Parameters + hex_literal::hex!( "c63bdd4a39095ccf55623a6f2872bf8a" // Pallet: "Parameters" + "c63bdd4a39095ccf55623a6f2872bf8a" // Storage Prefix: "Parameters" + // MoonbaseRuntimeRuntimeParamsRuntimeParametersKey(FeesTreasuryProportion) + "71d0aacb690b61280d0c97c6b6a666640000" + ) + .to_vec().into(), ]; diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs index 6108d9c228..dae752bd3a 100644 --- a/runtime/common/src/weights/mod.rs +++ b/runtime/common/src/weights/mod.rs @@ -36,6 +36,7 @@ pub mod pallet_moonbeam_lazy_migrations; pub mod pallet_moonbeam_orbiters; pub mod pallet_multisig; pub mod pallet_parachain_staking; +pub mod pallet_parameters; pub mod pallet_precompile_benchmarks; pub mod pallet_preimage; pub mod pallet_proxy; diff --git a/runtime/common/src/weights/pallet_parameters.rs b/runtime/common/src/weights/pallet_parameters.rs new file mode 100644 index 0000000000..ed4a72ba2b --- /dev/null +++ b/runtime/common/src/weights/pallet_parameters.rs @@ -0,0 +1,60 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for `pallet_parameters` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-08-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `COV0706`, CPU: `AMD Ryzen 9 7950X 16-Core Processor` +//! WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_parameters +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --template=./benchmarking/frame-weight-template.hbs +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_parameters`. +pub struct WeightInfo(PhantomData); +impl pallet_parameters::WeightInfo for WeightInfo { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + fn set_parameter() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3501` + // Minimum execution time: 5_480_000 picoseconds. + Weight::from_parts(5_610_000, 3501) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/runtime/moonbase/Cargo.toml b/runtime/moonbase/Cargo.toml index f059b33244..b12ede2a83 100644 --- a/runtime/moonbase/Cargo.toml +++ b/runtime/moonbase/Cargo.toml @@ -89,6 +89,7 @@ pallet-conviction-voting = { workspace = true } pallet-identity = { workspace = true } pallet-multisig = { workspace = true } pallet-preimage = { workspace = true } +pallet-parameters = { workspace = true } pallet-proxy = { workspace = true } pallet-referenda = { workspace = true } pallet-root-testing = { workspace = true } @@ -274,6 +275,7 @@ std = [ "pallet-parachain-staking/std", "pallet-precompile-benchmarks/std", "pallet-preimage/std", + "pallet-parameters/std", "pallet-proxy-genesis-companion/std", "pallet-proxy/std", "pallet-randomness/std", @@ -365,6 +367,7 @@ runtime-benchmarks = [ "pallet-parachain-staking/runtime-benchmarks", "pallet-precompile-benchmarks/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", + "pallet-parameters/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-randomness/runtime-benchmarks", "pallet-referenda/runtime-benchmarks", @@ -406,6 +409,7 @@ try-runtime = [ "pallet-moonbeam-lazy-migrations/try-runtime", "pallet-parachain-staking/try-runtime", "pallet-preimage/try-runtime", + "pallet-parameters/try-runtime", "pallet-referenda/try-runtime", "pallet-relay-storage-roots/try-runtime", "pallet-root-testing/try-runtime", diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 6a591538cd..387d2cff66 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -30,6 +30,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod asset_config; pub mod governance; +pub mod runtime_params; pub mod xcm_config; mod migrations; @@ -125,6 +126,8 @@ use xcm_config::AssetType; use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; use xcm_primitives::UnitsToWeightRatio; +use runtime_params::*; + use smallvec::smallvec; use sp_runtime::serde::{Deserialize, Serialize}; @@ -348,8 +351,11 @@ where mut fees_then_tips: impl Iterator>>, ) { if let Some(fees) = fees_then_tips.next() { - // for fees, 80% are burned, 20% to the treasury - let (_, to_treasury) = fees.ration(80, 20); + let treasury_perbill = + runtime_params::dynamic_params::runtime_config::FeesTreasuryProportion::get(); + let treasury_part = treasury_perbill.deconstruct(); + let burn_part = Perbill::one().deconstruct() - treasury_part; + let (_, to_treasury) = fees.ration(burn_part, treasury_part); // Balances pallet automatically burns dropped Credits by decreasing // total_supply accordingly ResolveTo::, pallet_balances::Pallet>::on_unbalanced( @@ -1379,6 +1385,13 @@ impl pallet_precompile_benchmarks::Config for Runtime { type WeightInfo = moonbase_weights::pallet_precompile_benchmarks::WeightInfo; } +impl pallet_parameters::Config for Runtime { + type AdminOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type RuntimeParameters = RuntimeParameters; + type WeightInfo = moonbase_weights::pallet_parameters::WeightInfo; +} + construct_runtime! { pub enum Runtime { @@ -1441,6 +1454,7 @@ construct_runtime! { MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 54, EmergencyParaXcm: pallet_emergency_para_xcm::{Pallet, Call, Storage, Event} = 55, EvmForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event} = 56, + Parameters: pallet_parameters = 57, } } @@ -1518,6 +1532,7 @@ mod benches { [pallet_relay_storage_roots, RelayStorageRoots] [pallet_precompile_benchmarks, PrecompileBenchmarks] [pallet_moonbeam_lazy_migrations, MoonbeamLazyMigrations] + [pallet_parameters, Parameters] ); } diff --git a/runtime/moonbase/src/runtime_params.rs b/runtime/moonbase/src/runtime_params.rs new file mode 100644 index 0000000000..4916cc27df --- /dev/null +++ b/runtime/moonbase/src/runtime_params.rs @@ -0,0 +1,44 @@ +// Copyright 2024 Moonbeam Foundation. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Dynamic runtime parametes. +use crate::Runtime; +use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params}; +use sp_runtime::Perbill; + +#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] +pub mod dynamic_params { + use super::*; + #[dynamic_pallet_params] + #[codec(index = 0)] + pub mod runtime_config { + // for fees, 80% are burned, 20% to the treasury + #[codec(index = 0)] + pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20); + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default for RuntimeParameters { + fn default() -> Self { + RuntimeParameters::RuntimeConfig( + dynamic_params::runtime_config::Parameters::FeesTreasuryProportion( + dynamic_params::runtime_config::FeesTreasuryProportion, + Some(Perbill::from_percent(20)), + ), + ) + } +} diff --git a/test/suites/dev/moonbase/test-parameters/test-parameters.ts b/test/suites/dev/moonbase/test-parameters/test-parameters.ts new file mode 100644 index 0000000000..8ff2b8cd9a --- /dev/null +++ b/test/suites/dev/moonbase/test-parameters/test-parameters.ts @@ -0,0 +1,87 @@ +import { describeSuite, DevModeContext, expect } from "@moonwall/cli"; +import "@moonbeam-network/api-augment"; +import { alith } from "@moonwall/util"; + +const UNIT = 1_000_000_000_000_000_000n; + +const RUNTIME = "MoonbaseRuntime"; +const CRATE = "RuntimeParams"; +const ALL_PARAMS = "DynamicParams"; + +function parameterType(context: DevModeContext, module: string, name: string, value: unknown) { + const paramWrapper = context + .polkadotJs() + .createType(`${RUNTIME}${CRATE}${ALL_PARAMS}${module}Parameters`, { + [name]: [null, value], + }); + + const runtimeParameter = context.polkadotJs().createType(`${RUNTIME}${CRATE}RuntimeParameters`, { + [module]: paramWrapper, + }); + + return runtimeParameter; +} + +function parameterKey(context: DevModeContext, module: string, name: string) { + const key = context + .polkadotJs() + .createType(`${RUNTIME}${CRATE}${ALL_PARAMS}${module}ParametersKey`, { + [name]: null, + }); + + const keyWrapper = context.polkadotJs().createType(`${RUNTIME}${CRATE}RuntimeParametersKey`, { + [module]: key, + }); + + return keyWrapper; +} + +describeSuite({ + id: "DTemp01", + title: "Parameters", + foundationMethods: "dev", + testCases: ({ it, context, log }) => { + let testCounter = 0; + function testParam(module: string, name: string, valueCreation: [string, unknown]) { + it({ + id: `T${testCounter++} - ${module} - ${name}`, + title: "Parameters cannot be changed by normal user", + test: async () => { + const value = context.polkadotJs().createType(valueCreation[0], valueCreation[1]); + const param = parameterType(context, module, name, value); + + const res = await context.createBlock( + context.polkadotJs().tx.parameters.setParameter(param.toU8a()).signAsync(alith), + { allowFailures: true } + ); + expect(res.result?.error?.name).toEqual("BadOrigin"); + }, + }); + + it({ + id: `T${testCounter++} - ${module} - ${name}`, + title: "Parameters can be changed by root user", + test: async () => { + const value = context.polkadotJs().createType(valueCreation[0], valueCreation[1]); + const param = parameterType(context, module, name, value); + + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.parameters.setParameter(param.toU8a())) + .signAsync(alith), + { allowFailures: false } + ); + + const key = parameterKey(context, module, name); + + const wrappedValue = await context.polkadotJs().query.parameters.parameters(key.toU8a()); + const gotValue = wrappedValue.value.value.value.toU8a(); + expect(gotValue).toEqual(value.toU8a()); + }, + }); + } + + testParam("RuntimeConfig", "FeesTreasuryProportion", ["Perbill", 200_000_000]); + }, +});