referrerpolicy=no-referrer-when-downgrade

pallet_default_config_example/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: MIT-0
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy of
7// this software and associated documentation files (the "Software"), to deal in
8// the Software without restriction, including without limitation the rights to
9// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10// of the Software, and to permit persons to whom the Software is furnished to do
11// so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in all
14// copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22// SOFTWARE.
23
24//! # Default Config Pallet Example
25//!
26//! A simple example of a FRAME pallet that utilizes [`frame_support::derive_impl`] to demonstrate
27//! the simpler way to implement `Config` trait of pallets. This example only showcases this in a
28//! `mock.rs` environment, but the same applies to a real runtime as well.
29//!
30//! See the source code of [`tests`] for a real examples.
31//!
32//! Study the following types:
33//!
34//! - [`pallet::DefaultConfig`], and how it differs from [`pallet::Config`].
35//! - [`struct@pallet::config_preludes::TestDefaultConfig`] and how it implements
36//!   [`pallet::DefaultConfig`].
37//! - Notice how [`pallet::DefaultConfig`] is independent of [`frame_system::Config`].
38
39#![cfg_attr(not(feature = "std"), no_std)]
40
41extern crate alloc;
42
43#[frame_support::pallet]
44pub mod pallet {
45	use frame_support::pallet_prelude::*;
46
47	/// This pallet is annotated to have a default config. This will auto-generate
48	/// [`DefaultConfig`].
49	///
50	/// It will be an identical, but won't have anything that is `#[pallet::no_default]`.
51	#[pallet::config(with_default)]
52	pub trait Config: frame_system::Config {
53		/// The overarching task type. This is coming from the runtime, and cannot have a default.  
54		/// In general, `Runtime*`-oriented types cannot have a sensible default.
55		#[pallet::no_default] // optional. `RuntimeEvent` is automatically excluded as well.
56		type RuntimeTask: Task;
57
58		/// An input parameter to this pallet. This value can have a default, because it is not
59		/// reliant on `frame_system::Config` or the overarching runtime in any way.
60		type WithDefaultValue: Get<u32>;
61
62		/// Same as [`Config::WithDefaultValue`], but we don't intend to define a default for this
63		/// in our tests below.
64		type OverwrittenDefaultValue: Get<u32>;
65
66		/// An input parameter that relies on `<Self as frame_system::Config>::AccountId`. This can
67		/// too have a default, as long as it is present in `frame_system::DefaultConfig`.
68		type CanDeriveDefaultFromSystem: Get<Self::AccountId>;
69
70		/// We might choose to declare as one that doesn't have a default, for whatever semantical
71		/// reason.
72		#[pallet::no_default]
73		type HasNoDefault: Get<u32>;
74
75		/// Some types can technically have no default, such as those the rely on
76		/// `frame_system::Config` but are not present in `frame_system::DefaultConfig`. For
77		/// example, a `RuntimeCall` cannot reasonably have a default.
78		#[pallet::no_default] // if we skip this, there will be a compiler error.
79		type CannotHaveDefault: Get<Self::RuntimeCall>;
80
81		/// Something that is a normal type, with default.
82		type WithDefaultType;
83
84		/// Same as [`Config::WithDefaultType`], but we don't intend to define a default for this
85		/// in our tests below.
86		type OverwrittenDefaultType;
87	}
88
89	/// Container for different types that implement [`DefaultConfig`]` of this pallet.
90	pub mod config_preludes {
91		// This will help use not need to disambiguate anything when using `derive_impl`.
92		use super::*;
93		use frame_support::derive_impl;
94
95		/// A type providing default configurations for this pallet in testing environment.
96		pub struct TestDefaultConfig;
97
98		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
99		impl frame_system::DefaultConfig for TestDefaultConfig {}
100
101		#[frame_support::register_default_impl(TestDefaultConfig)]
102		impl DefaultConfig for TestDefaultConfig {
103			type WithDefaultValue = frame_support::traits::ConstU32<42>;
104			type OverwrittenDefaultValue = frame_support::traits::ConstU32<42>;
105
106			// `frame_system::config_preludes::TestDefaultConfig` declares account-id as u64.
107			type CanDeriveDefaultFromSystem = frame_support::traits::ConstU64<42>;
108
109			type WithDefaultType = u32;
110			type OverwrittenDefaultType = u32;
111		}
112
113		/// A type providing default configurations for this pallet in another environment. Examples
114		/// could be a parachain, or a solochain.
115		///
116		/// Appropriate derive for `frame_system::DefaultConfig` needs to be provided. In this
117		/// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again.
118		pub struct OtherDefaultConfig;
119
120		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
121		impl frame_system::DefaultConfig for OtherDefaultConfig {}
122
123		#[frame_support::register_default_impl(OtherDefaultConfig)]
124		impl DefaultConfig for OtherDefaultConfig {
125			type WithDefaultValue = frame_support::traits::ConstU32<66>;
126			type OverwrittenDefaultValue = frame_support::traits::ConstU32<66>;
127			type CanDeriveDefaultFromSystem = frame_support::traits::ConstU64<42>;
128			type WithDefaultType = u32;
129			type OverwrittenDefaultType = u32;
130		}
131	}
132
133	#[pallet::pallet]
134	pub struct Pallet<T>(_);
135
136	#[pallet::event]
137	pub enum Event<T: Config> {}
138}
139
140#[cfg(any(test, doc))]
141pub mod tests {
142	use super::*;
143	use frame_support::{derive_impl, parameter_types};
144	use pallet::{self as pallet_default_config_example, config_preludes::*};
145
146	type Block = frame_system::mocking::MockBlock<Runtime>;
147
148	frame_support::construct_runtime!(
149		pub enum Runtime {
150			System: frame_system,
151			DefaultPallet: pallet_default_config_example,
152		}
153	);
154
155	#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
156	impl frame_system::Config for Runtime {
157		// these items are defined by frame-system as `no_default`, so we must specify them here.
158		type Block = Block;
159
160		// all of this is coming from `frame_system::config_preludes::TestDefaultConfig`.
161
162		// type Nonce = u32;
163		// type BlockNumber = u32;
164		// type Hash = sp_core::hash::H256;
165		// type Hashing = sp_runtime::traits::BlakeTwo256;
166		// type AccountId = u64;
167		// type Lookup = sp_runtime::traits::IdentityLookup<u64>;
168		// type BlockHashCount = frame_support::traits::ConstU32<10>;
169		// type MaxConsumers = frame_support::traits::ConstU32<16>;
170		// type AccountData = ();
171		// type OnNewAccount = ();
172		// type OnKilledAccount = ();
173		// type SystemWeightInfo = ();
174		// type SS58Prefix = ();
175		// type Version = ();
176		// type BlockWeights = ();
177		// type BlockLength = ();
178		// type DbWeight = ();
179		// type BaseCallFilter = frame_support::traits::Everything;
180		// type BlockHashCount = frame_support::traits::ConstU64<10>;
181		// type OnSetCode = ();
182
183		// These are marked as `#[inject_runtime_type]`. Hence, they are being injected as
184		// types generated by `construct_runtime`.
185
186		// type RuntimeOrigin = RuntimeOrigin;
187		// type RuntimeCall = RuntimeCall;
188		// type RuntimeEvent = RuntimeEvent;
189		// type PalletInfo = PalletInfo;
190
191		// you could still overwrite any of them if desired.
192		type SS58Prefix = frame_support::traits::ConstU16<456>;
193	}
194
195	parameter_types! {
196		pub const SomeCall: RuntimeCall = RuntimeCall::System(frame_system::Call::<Runtime>::remark { remark: alloc::vec![] });
197	}
198
199	#[derive_impl(TestDefaultConfig as pallet::DefaultConfig)]
200	impl pallet_default_config_example::Config for Runtime {
201		// This cannot have default.
202		type RuntimeTask = RuntimeTask;
203
204		type HasNoDefault = frame_support::traits::ConstU32<1>;
205		type CannotHaveDefault = SomeCall;
206
207		type OverwrittenDefaultValue = frame_support::traits::ConstU32<678>;
208		type OverwrittenDefaultType = u128;
209	}
210
211	#[test]
212	fn it_works() {
213		use frame_support::traits::Get;
214		use pallet::{Config, DefaultConfig};
215
216		// assert one of the value types that is not overwritten.
217		assert_eq!(
218			<<Runtime as Config>::WithDefaultValue as Get<u32>>::get(),
219			<<TestDefaultConfig as DefaultConfig>::WithDefaultValue as Get<u32>>::get()
220		);
221
222		// assert one of the value types that is overwritten.
223		assert_eq!(<<Runtime as Config>::OverwrittenDefaultValue as Get<u32>>::get(), 678u32);
224
225		// assert one of the types that is not overwritten.
226		assert_eq!(
227			std::any::TypeId::of::<<Runtime as Config>::WithDefaultType>(),
228			std::any::TypeId::of::<<TestDefaultConfig as DefaultConfig>::WithDefaultType>()
229		);
230
231		// assert one of the types that is overwritten.
232		assert_eq!(
233			std::any::TypeId::of::<<Runtime as Config>::OverwrittenDefaultType>(),
234			std::any::TypeId::of::<u128>()
235		)
236	}
237}