diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 61939a2c80a7..3690c81cb788 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -58,9 +58,11 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, ord_parameter_types, parameter_types, traits::{ - fungible, fungibles, tokens::imbalance::ResolveAssetTo, AsEnsureOriginWithArg, ConstBool, - ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Equals, InstanceFilter, - TransformOrigin, + fungible::{self, HoldConsideration}, + fungibles, + tokens::imbalance::ResolveAssetTo, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + Equals, InstanceFilter, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, BoundedVec, PalletId, @@ -215,7 +217,8 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = (); // We allow each account to have holds on it from: // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + // - `Multisig`: 1 + type MaxHolds = ConstU32<2>; type MaxFreezes = ConstU32<0>; } @@ -409,14 +412,19 @@ parameter_types! { // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u32 = 100; + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -912,7 +920,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, // Bridge utilities. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index e0dff0c4516e..60905fd7430c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -40,10 +40,11 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, ord_parameter_types, parameter_types, traits::{ - fungible, fungibles, + fungible::{self, HoldConsideration}, + fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, - InstanceFilter, TransformOrigin, + InstanceFilter, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, BoundedVec, PalletId, @@ -200,7 +201,8 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = (); // We allow each account to have holds on it from: // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + // - `Multisig`: 1 + type MaxHolds = ConstU32<2>; type MaxFreezes = ConstU32<0>; } @@ -389,14 +391,19 @@ parameter_types! { // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u32 = 100; + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -891,7 +898,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, // The main stage. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index b21cde248e11..fb4ef47025eb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -61,7 +61,10 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU32, ConstU64, ConstU8, TransformOrigin}, + traits::{ + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, LinearStoragePrice, + TransformOrigin, + }, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -312,7 +315,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -476,14 +481,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -670,7 +680,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 36, // Bridge relayers pallet, used by several bridges here. BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 717cde6280db..8d6ef65aab4b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -57,7 +57,10 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU32, ConstU64, ConstU8, TransformOrigin}, + traits::{ + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, LinearStoragePrice, + TransformOrigin, + }, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -278,7 +281,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -434,14 +439,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -483,7 +493,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 36, // Bridging stuff. BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 41, diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 6cb8e096e4b3..3b23d958a942 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -211,7 +211,10 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<1>; + // We allow each account to have holds on it from: + // - `Preimage`: 1 + // - `Multisig`: 1 + type MaxHolds = ConstU32<2>; type MaxFreezes = ConstU32<0>; } @@ -235,14 +238,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -661,7 +669,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, Preimage: pallet_preimage::{Pallet, Call, Storage, Event, HoldReason} = 43, Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 44, diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 79b6b6be299b..1cb57f9a17c5 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -50,7 +50,10 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8}, + traits::{ + fungible::HoldConsideration, ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, + LinearStoragePrice, + }, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -217,7 +220,10 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<1>; + // We allow each account to have holds on it from: + // - `Contracts`: 1 + // - `Multisig`: 1 + type MaxHolds = ConstU32<2>; type MaxFreezes = ConstU32<0>; } @@ -241,14 +247,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } @@ -406,7 +417,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 50, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 51, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 51, // Sudo Sudo: pallet_sudo::{Pallet, Call, Config, Event, Storage} = 100, diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 0f01c2d74166..68b921ba4789 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -40,7 +40,10 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin}, + traits::{ + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + LinearStoragePrice, TransformOrigin, + }, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -228,7 +231,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -399,14 +404,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); /// Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 742b3a29275c..5769324421bd 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -31,7 +31,10 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin}, + traits::{ + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + LinearStoragePrice, TransformOrigin, + }, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -219,7 +222,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -390,14 +395,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); /// Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 7805e0ad9829..109025c30fdf 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -30,8 +30,8 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - ConstBool, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EverythingBut, - TransformOrigin, + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, Contains, + EitherOfDiverse, EverythingBut, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, PalletId, @@ -218,7 +218,9 @@ impl pallet_balances::Config for Runtime { type RuntimeFreezeReason = RuntimeFreezeReason; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -376,14 +378,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -434,7 +441,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 41, // The main stage. Identity: pallet_identity::{Pallet, Call, Storage, Event} = 50, diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 8ea29c8aa218..9feb22d6dd69 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -30,8 +30,8 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - ConstBool, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EverythingBut, - TransformOrigin, + fungible::HoldConsideration, ConstBool, ConstU32, ConstU64, ConstU8, Contains, + EitherOfDiverse, EverythingBut, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, PalletId, @@ -218,7 +218,9 @@ impl pallet_balances::Config for Runtime { type RuntimeFreezeReason = RuntimeFreezeReason; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Multisig`: 1 + type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } @@ -376,14 +378,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -434,7 +441,7 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 41, // The main stage. Identity: pallet_identity::{Pallet, Call, Storage, Event} = 50, diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 67caa347bc38..ba4e70a7a62b 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -317,7 +317,11 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; - type MaxHolds = ConstU32<2>; + // We allow each account to have holds on it from: + // - `Nis`: 1 + // - `Preimage`: 1 + // - `Multisig`: 1 + type MaxHolds = ConstU32<3>; } parameter_types! { @@ -684,14 +688,19 @@ parameter_types! { // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u32 = 100; + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -1163,7 +1172,11 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<2>; + // We allow each account to have holds on it from: + // - `Nis`: 1 + // - `Preimage`: 1 + // - `Multisig`: 1 + type MaxHolds = ConstU32<3>; type MaxFreezes = ConstU32<1>; } @@ -1377,7 +1390,7 @@ construct_runtime! { Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 30, // Multisig module. Late addition. - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 31, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 31, // Preimage registrar. Preimage: pallet_preimage::{Pallet, Call, Storage, Event, HoldReason} = 32, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index e0b9fd0fb53e..0d5324ac842a 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -304,7 +304,10 @@ impl pallet_balances::Config for Runtime { type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; - type MaxHolds = ConstU32<1>; + // We allow each account to have holds on it from: + // - `Preimage`: 1 + // - `Multisig`: 1 + type MaxHolds = ConstU32<2>; } parameter_types! { @@ -894,14 +897,19 @@ parameter_types! { // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u32 = 100; + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::WeightInfo; } @@ -1442,7 +1450,7 @@ construct_runtime! { Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 22, // Multisig module. Late addition. - Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 23, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event, HoldReason} = 23, // Election pallet. Only works with staking, but placed here to maintain indices. ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event, ValidateUnsigned} = 24, diff --git a/prdoc/pr_1782.prdoc b/prdoc/pr_1782.prdoc new file mode 100644 index 000000000000..28deb5bb83de --- /dev/null +++ b/prdoc/pr_1782.prdoc @@ -0,0 +1,16 @@ +title: Migrates pallet-multisig to Consideration API + +doc: + - audience: Runtime Dev + description: | + Migrates Multisig pallet to use Consideration - an abstraction over storage deposits introduced in https://github.com/paritytech/polkadot-sdk/pull/1361 + +migrations: + db: [] + + runtime: [] + +crates: + - name: pallet-multisig + +host_functions: [] \ No newline at end of file diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 6e7bfb4f4b42..4fe6728d2373 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -330,14 +330,19 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); + pub const MultisigHoldReason: RuntimeHoldReason = RuntimeHoldReason::Multisig(pallet_multisig::HoldReason::Multisig); } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; + type Consideration = HoldConsideration< + AccountId, + Balances, + MultisigHoldReason, + LinearStoragePrice, + >; type MaxSignatories = ConstU32<100>; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } @@ -533,7 +538,7 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; - type MaxHolds = ConstU32<6>; + type MaxHolds = ConstU32<7>; } parameter_types! { diff --git a/substrate/frame/multisig/src/benchmarking.rs b/substrate/frame/multisig/src/benchmarking.rs index ebe19df5dc43..014031181e7a 100644 --- a/substrate/frame/multisig/src/benchmarking.rs +++ b/substrate/frame/multisig/src/benchmarking.rs @@ -81,7 +81,7 @@ benchmarks! { frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); }: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, Weight::zero()) verify { - assert!(Multisigs::::contains_key(multi_account_id, call_hash)); + assert!(MultisigsFor::::contains_key(multi_account_id, call_hash)); } as_multi_approve { @@ -104,7 +104,7 @@ benchmarks! { frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::zero()) verify { - let multisig = Multisigs::::get(multi_account_id, call_hash).ok_or("multisig not created")?; + let multisig = MultisigsFor::::get(multi_account_id, call_hash).ok_or("multisig not created")?; assert_eq!(multisig.approvals.len(), 2); } @@ -130,13 +130,13 @@ benchmarks! { Multisig::::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), Weight::zero())?; } let caller2 = signatories2.remove(0); - assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + assert!(MultisigsFor::::contains_key(&multi_account_id, call_hash)); // Whitelist caller account from further DB operations. let caller_key = frame_system::Account::::hashed_key_for(&caller2); frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::MAX) verify { - assert!(!Multisigs::::contains_key(&multi_account_id, call_hash)); + assert!(!MultisigsFor::::contains_key(&multi_account_id, call_hash)); } approve_as_multi_create { @@ -154,7 +154,7 @@ benchmarks! { // Create the multi }: approve_as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call_hash, Weight::zero()) verify { - assert!(Multisigs::::contains_key(multi_account_id, call_hash)); + assert!(MultisigsFor::::contains_key(multi_account_id, call_hash)); } approve_as_multi_approve { @@ -184,7 +184,7 @@ benchmarks! { frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); }: approve_as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call_hash, Weight::zero()) verify { - let multisig = Multisigs::::get(multi_account_id, call_hash).ok_or("multisig not created")?; + let multisig = MultisigsFor::::get(multi_account_id, call_hash).ok_or("multisig not created")?; assert_eq!(multisig.approvals.len(), 2); } @@ -201,13 +201,13 @@ benchmarks! { // Create the multi let o = RawOrigin::Signed(caller.clone()).into(); Multisig::::as_multi(o, s as u16, signatories.clone(), None, call, Weight::zero())?; - assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + assert!(MultisigsFor::::contains_key(&multi_account_id, call_hash)); // Whitelist caller account from further DB operations. let caller_key = frame_system::Account::::hashed_key_for(&caller); frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); }: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash) verify { - assert!(!Multisigs::::contains_key(multi_account_id, call_hash)); + assert!(!MultisigsFor::::contains_key(multi_account_id, call_hash)); } impl_benchmark_test_suite!(Multisig, crate::tests::new_test_ext(), crate::tests::Test); diff --git a/substrate/frame/multisig/src/lib.rs b/substrate/frame/multisig/src/lib.rs index e4426c64b412..8b87c7acd173 100644 --- a/substrate/frame/multisig/src/lib.rs +++ b/substrate/frame/multisig/src/lib.rs @@ -55,7 +55,7 @@ use frame_support::{ PostDispatchInfo, }, ensure, - traits::{Currency, Get, ReservableCurrency}, + traits::{Consideration, Currency, Defensive, Footprint, Get, ReservableCurrency}, weights::Weight, BoundedVec, }; @@ -63,7 +63,7 @@ use frame_system::{self as system, pallet_prelude::BlockNumberFor, RawOrigin}; use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ - traits::{Dispatchable, TrailingZeroInput, Zero}, + traits::{Dispatchable, TrailingZeroInput}, DispatchError, RuntimeDebug, }; use sp_std::prelude::*; @@ -104,7 +104,7 @@ pub struct Timepoint { /// An open multisig operation. #[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(MaxApprovals))] -pub struct Multisig +pub struct OldMultisig where MaxApprovals: Get, { @@ -118,14 +118,34 @@ where approvals: BoundedVec, } +/// An open multisig operation. +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(MaxApprovals))] +pub struct Multisig +where + MaxApprovals: Get, +{ + /// The extrinsic when the multisig operation was opened. + when: Timepoint, + /// The amount held in reserve of the `depositor`, to be returned once the operation ends. + ticket: Ticket, + /// The account who opened it (i.e. the first to approve it). + depositor: AccountId, + /// The approvals achieved so far, including the depositor. Always sorted. + approvals: BoundedVec, +} + type CallHash = [u8; 32]; +type TicketOf = ::Consideration; + enum CallOrHash { Call(::RuntimeCall), Hash([u8; 32]), } #[frame_support::pallet] +#[allow(deprecated)] pub mod pallet { use super::*; use frame_support::pallet_prelude::*; @@ -145,20 +165,8 @@ pub mod pallet { /// The currency mechanism. type Currency: ReservableCurrency; - /// The base amount of currency needed to reserve for creating a multisig execution or to - /// store a dispatch call for later. - /// - /// This is held for an additional storage item whose value size is - /// `4 + sizeof((BlockNumber, Balance, AccountId))` bytes and whose key size is - /// `32 + sizeof(AccountId)` bytes. - #[pallet::constant] - type DepositBase: Get>; - - /// The amount of currency needed per unit threshold when creating a multisig execution. - /// - /// This is held for adding 32 bytes more into a pre-existing storage value. - #[pallet::constant] - type DepositFactor: Get>; + /// A means of providing some cost while data is stored on-chain. + type Consideration: Consideration; /// The maximum amount of signatories allowed in the multisig. #[pallet::constant] @@ -176,6 +184,7 @@ pub mod pallet { pub struct Pallet(_); /// The set of open multisig operations. + #[deprecated = "MultisigsFor"] #[pallet::storage] pub type Multisigs = StorageDoubleMap< _, @@ -183,7 +192,18 @@ pub mod pallet { T::AccountId, Blake2_128Concat, [u8; 32], - Multisig, BalanceOf, T::AccountId, T::MaxSignatories>, + OldMultisig, BalanceOf, T::AccountId, T::MaxSignatories>, + >; + + /// The set of open multisig operations. + #[pallet::storage] + pub type MultisigsFor = StorageDoubleMap< + _, + Twox64Concat, + T::AccountId, + Blake2_128Concat, + [u8; 32], + Multisig, TicketOf, T::AccountId, T::MaxSignatories>, >; #[pallet::error] @@ -218,6 +238,13 @@ pub mod pallet { AlreadyStored, } + /// A reason for this pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + /// The funds are held as storage deposit for a multisig. + Multisig, + } + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -476,14 +503,14 @@ pub mod pallet { let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; let id = Self::multi_account_id(&signatories, threshold); + Self::ensure_updated(&id, &call_hash, threshold); - let m = >::get(&id, call_hash).ok_or(Error::::NotFound)?; + let m = >::get(&id, call_hash).ok_or(Error::::NotFound)?; ensure!(m.when == timepoint, Error::::WrongTimepoint); ensure!(m.depositor == who, Error::::NotOwner); - let err_amount = T::Currency::unreserve(&m.depositor, m.deposit); - debug_assert!(err_amount.is_zero()); - >::remove(&id, &call_hash); + let _ = m.ticket.drop(&m.depositor); + >::remove(&id, &call_hash); Self::deposit_event(Event::MultisigCancelled { cancelling: who, @@ -533,8 +560,10 @@ impl Pallet { CallOrHash::Hash(h) => (h, 0, None), }; + Self::ensure_updated(&id, &call_hash, threshold); + // Branch on whether the operation has already started or not. - if let Some(mut m) = >::get(&id, call_hash) { + if let Some(mut m) = >::get(&id, call_hash) { // Yes; ensure that the timepoint exists and agrees. let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; ensure!(m.when == timepoint, Error::::WrongTimepoint); @@ -558,8 +587,8 @@ impl Pallet { // Clean up storage before executing call to avoid an possibility of reentrancy // attack. - >::remove(&id, call_hash); - T::Currency::unreserve(&m.depositor, m.deposit); + >::remove(&id, call_hash); + let _ = m.ticket.drop(&m.depositor); let result = call.dispatch(RawOrigin::Signed(id.clone()).into()); Self::deposit_event(Event::MultisigExecuted { @@ -587,7 +616,7 @@ impl Pallet { m.approvals .try_insert(pos, who.clone()) .map_err(|_| Error::::TooManySignatories)?; - >::insert(&id, call_hash, m); + >::insert(&id, call_hash, m); Self::deposit_event(Event::MultisigApproval { approving: who, timepoint, @@ -609,20 +638,17 @@ impl Pallet { // Not yet started; there should be no timepoint given. ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); - // Just start the operation by recording it in storage. - let deposit = T::DepositBase::get() + T::DepositFactor::get() * threshold.into(); - - T::Currency::reserve(&who, deposit)?; + let ticket = T::Consideration::new(&who, Footprint::from_parts(1, threshold as usize))?; let initial_approvals = vec![who.clone()].try_into().map_err(|_| Error::::TooManySignatories)?; - >::insert( + >::insert( &id, call_hash, Multisig { when: Self::timepoint(), - deposit, + ticket, depositor: who.clone(), approvals: initial_approvals, }, @@ -665,6 +691,25 @@ impl Pallet { signatories.insert(index, who); Ok(signatories) } + + pub(crate) fn ensure_updated(id: &T::AccountId, call_hash: &[u8; 32], threshold: u16) -> bool { + #[allow(deprecated)] + let r = match Multisigs::::take(id, call_hash) { + Some(r) => r, + None => return false, + }; + T::Currency::unreserve(&r.depositor, r.deposit); + // take consideration + let Ok(ticket) = + T::Consideration::new(&r.depositor, Footprint::from_parts(1, threshold as usize)) + .defensive_proof("Unexpected inability to take deposit after unreserved") + else { + return true + }; + let n = Multisig { when: r.when, ticket, depositor: r.depositor, approvals: r.approvals }; + MultisigsFor::::insert(id, call_hash, n); + true + } } /// Return the weight of a dispatch call result as an `Option`. diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs index 179827255291..e0815066e4d6 100644 --- a/substrate/frame/multisig/src/tests.rs +++ b/substrate/frame/multisig/src/tests.rs @@ -24,9 +24,9 @@ use super::*; use crate as pallet_multisig; use frame_support::{ assert_noop, assert_ok, derive_impl, - traits::{ConstU32, ConstU64, Contains}, + traits::{fungible::HoldConsideration, ConstU32, Contains}, }; -use sp_runtime::{BuildStorage, TokenError}; +use sp_runtime::{bounded_vec, traits::Convert, BuildStorage, TokenError}; type Block = frame_system::mocking::MockBlockU32; @@ -51,6 +51,8 @@ impl frame_system::Config for Test { impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; + type RuntimeHoldReason = (); + type MaxHolds = ConstU32<2>; } pub struct TestBaseCallFilter; @@ -64,12 +66,19 @@ impl Contains for TestBaseCallFilter { } } } + +pub struct ConvertDeposit; +impl Convert for ConvertDeposit { + fn convert(a: Footprint) -> u64 { + a.count + a.size + } +} + impl Config for Test { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type DepositBase = ConstU64<1>; - type DepositFactor = ConstU64<1>; + type Consideration = HoldConsideration; type MaxSignatories = ConstU32<3>; type WeightInfo = (); } @@ -96,6 +105,24 @@ fn call_transfer(dest: u64, value: u64) -> Box { Box::new(RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value })) } +/// Insert an un-migrated multisig. +pub fn insert_old_multisig( + id: &T::AccountId, + call_hash: &[u8; 32], + depositor: T::AccountId, +) { + let when: Timepoint> = crate::Pallet::::timepoint(); + let deposit: BalanceOf = 123u32.into(); + let n = OldMultisig { + when, + deposit, + depositor: depositor.clone(), + approvals: bounded_vec!(depositor), + }; + #[allow(deprecated)] + Multisigs::::insert(id, call_hash, n); +} + #[test] fn multisig_deposit_is_taken_and_returned() { new_test_ext().execute_with(|| { @@ -692,3 +719,24 @@ fn multisig_handles_no_preimage_after_all_approve() { assert_eq!(Balances::free_balance(6), 15); }); } + +#[test] +fn ensure_updated_works() { + #![allow(deprecated)] + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3); + + let call = call_transfer(6, 15); + let call_hash = blake2_256(&call.encode()); + + insert_old_multisig::(&multi, &call_hash, 1); + assert_eq!(Multisigs::::iter().count(), 1); + + assert_eq!(Multisig::ensure_updated(&multi, &call_hash, 3), true); + assert_eq!(Multisigs::::iter().count(), 0); + assert_eq!(MultisigsFor::::iter().count(), 1); + + let updated_multisig = MultisigsFor::::get(&multi, &call_hash).unwrap(); + assert_eq!(updated_multisig.depositor, 1); + }); +}