|
| 1 | +// This file is part of Substrate. |
| 2 | + |
| 3 | +// Copyright (C) Parity Technologies (UK) Ltd. |
| 4 | +// SPDX-License-Identifier: Apache-2.0 |
| 5 | + |
| 6 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | +// you may not use this file except in compliance with the License. |
| 8 | +// You may obtain a copy of the License at |
| 9 | +// |
| 10 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +// |
| 12 | +// Unless required by applicable law or agreed to in writing, software |
| 13 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | +// See the License for the specific language governing permissions and |
| 16 | +// limitations under the License. |
| 17 | + |
| 18 | +//! # Default Config Pallet Example |
| 19 | +//! |
| 20 | +//! A simple example of a FRAME pallet that utilizes [`frame_support::derive_impl`] to demonstrate |
| 21 | +//! the simpler way to implement `Config` trait of pallets. This example only showcases this in a |
| 22 | +//! `mock.rs` environment, but the same applies to a real runtime as well. |
| 23 | +//! |
| 24 | +//! See the source code of [`tests`] for a real examples. |
| 25 | +//! |
| 26 | +//! Study the following types: |
| 27 | +//! |
| 28 | +//! - [`pallet::DefaultConfig`], and how it differs from [`pallet::Config`]. |
| 29 | +//! - [`pallet::config_preludes::TestDefaultConfig`] and how it implements |
| 30 | +//! [`pallet::DefaultConfig`]. |
| 31 | +//! - Notice how [`pallet::DefaultConfig`] is independent of [`frame_system::Config`]. |
| 32 | +
|
| 33 | +#![cfg_attr(not(feature = "std"), no_std)] |
| 34 | + |
| 35 | +#[frame_support::pallet] |
| 36 | +pub mod pallet { |
| 37 | + use frame_support::pallet_prelude::*; |
| 38 | + |
| 39 | + /// This pallet is annotated to have a default config. This will auto-generate |
| 40 | + /// [`DefaultConfig`]. |
| 41 | + /// |
| 42 | + /// It will be an identical, but won't have anything that is `#[pallet::no_default]`. |
| 43 | + #[pallet::config(with_default)] |
| 44 | + pub trait Config: frame_system::Config { |
| 45 | + /// The overarching event type. This is coming from the runtime, and cannot have a default. |
| 46 | + /// In general, `Runtime*`-oriented types cannot have a sensible default. |
| 47 | + #[pallet::no_default] // optional. `RuntimeEvent` is automatically excluded as well. |
| 48 | + type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; |
| 49 | + |
| 50 | + /// An input parameter to this pallet. This value can have a default, because it is not |
| 51 | + /// reliant on `frame_system::Config` or the overarching runtime in any way. |
| 52 | + type WithDefaultValue: Get<u32>; |
| 53 | + |
| 54 | + /// Same as [`Config::WithDefaultValue`], but we don't intend to define a default for this |
| 55 | + /// in our tests below. |
| 56 | + type OverwrittenDefaultValue: Get<u32>; |
| 57 | + |
| 58 | + /// An input parameter that relies on `<Self as frame_system::Config>::AccountId`. As of |
| 59 | + /// now, such types cannot have defaults and need to be annotated as such, iff |
| 60 | + /// `#[pallet::config(with_default)]` is enabled: |
| 61 | + #[pallet::no_default] |
| 62 | + type CannotHaveDefault: Get<Self::AccountId>; |
| 63 | + |
| 64 | + /// Something that is a normal type, with default. |
| 65 | + type WithDefaultType; |
| 66 | + |
| 67 | + /// Same as [`Config::WithDefaultType`], but we don't intend to define a default for this |
| 68 | + /// in our tests below. |
| 69 | + type OverwrittenDefaultType; |
| 70 | + } |
| 71 | + |
| 72 | + /// Container for different types that implement [`DefaultConfig`]` of this pallet. |
| 73 | + pub mod config_preludes { |
| 74 | + // This will help use not need to disambiguate anything when using `derive_impl`. |
| 75 | + use super::*; |
| 76 | + |
| 77 | + /// A type providing default configurations for this pallet in testing environment. |
| 78 | + pub struct TestDefaultConfig; |
| 79 | + #[frame_support::register_default_impl(TestDefaultConfig)] |
| 80 | + impl DefaultConfig for TestDefaultConfig { |
| 81 | + type WithDefaultValue = frame_support::traits::ConstU32<42>; |
| 82 | + type OverwrittenDefaultValue = frame_support::traits::ConstU32<42>; |
| 83 | + |
| 84 | + type WithDefaultType = u32; |
| 85 | + type OverwrittenDefaultType = u32; |
| 86 | + } |
| 87 | + |
| 88 | + /// A type providing default configurations for this pallet in a parachain environment. |
| 89 | + pub struct ParachainDefaultConfig; |
| 90 | + #[frame_support::register_default_impl(ParachainDefaultConfig)] |
| 91 | + impl DefaultConfig for ParachainDefaultConfig { |
| 92 | + type WithDefaultValue = frame_support::traits::ConstU32<66>; |
| 93 | + type OverwrittenDefaultValue = frame_support::traits::ConstU32<66>; |
| 94 | + type WithDefaultType = u32; |
| 95 | + type OverwrittenDefaultType = u32; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + #[pallet::pallet] |
| 100 | + pub struct Pallet<T>(_); |
| 101 | + |
| 102 | + #[pallet::event] |
| 103 | + pub enum Event<T: Config> {} |
| 104 | +} |
| 105 | + |
| 106 | +#[cfg(any(test, doc))] |
| 107 | +pub mod tests { |
| 108 | + use super::*; |
| 109 | + |
| 110 | + use frame_support::macro_magic::use_attr; |
| 111 | + // Because `derive_impl` is a [macro_magic](https://crates.io/crates/macro_magic) attribute |
| 112 | + // macro, [`#[use_attr]`](`frame_support::macro_magic::use_attr`) must be attached to any use |
| 113 | + // statement that brings it into scope. |
| 114 | + #[use_attr] |
| 115 | + use frame_support::derive_impl; |
| 116 | + |
| 117 | + use super::pallet as pallet_default_config_example; |
| 118 | + |
| 119 | + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>; |
| 120 | + type Block = frame_system::mocking::MockBlock<Test>; |
| 121 | + |
| 122 | + frame_support::construct_runtime!( |
| 123 | + pub enum Test where |
| 124 | + Block = Block, |
| 125 | + NodeBlock = Block, |
| 126 | + UncheckedExtrinsic = UncheckedExtrinsic, |
| 127 | + { |
| 128 | + System: frame_system, |
| 129 | + DefaultPallet: pallet_default_config_example, |
| 130 | + } |
| 131 | + ); |
| 132 | + |
| 133 | + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] |
| 134 | + impl frame_system::Config for Test { |
| 135 | + // these items are defined by frame-system as `no_default`, so we must specify them here. |
| 136 | + // Note that these are types that actually rely on the outer runtime, and can't sensibly |
| 137 | + // have an _independent_ default. |
| 138 | + type BaseCallFilter = frame_support::traits::Everything; |
| 139 | + type RuntimeOrigin = RuntimeOrigin; |
| 140 | + type RuntimeCall = RuntimeCall; |
| 141 | + type RuntimeEvent = RuntimeEvent; |
| 142 | + type PalletInfo = PalletInfo; |
| 143 | + type OnSetCode = (); |
| 144 | + |
| 145 | + // all of this is coming from `frame_system::config_preludes::TestDefaultConfig`. |
| 146 | + |
| 147 | + // type Index = u32; |
| 148 | + // type BlockNumber = u32; |
| 149 | + // type Header = sp_runtime::generic::Header<Self::BlockNumber, Self::Hashing>; |
| 150 | + // type Hash = sp_core::hash::H256; |
| 151 | + // type Hashing = sp_runtime::traits::BlakeTwo256; |
| 152 | + // type AccountId = u64; |
| 153 | + // type Lookup = sp_runtime::traits::IdentityLookup<u64>; |
| 154 | + // type BlockHashCount = frame_support::traits::ConstU32<10>; |
| 155 | + // type MaxConsumers = frame_support::traits::ConstU32<16>; |
| 156 | + // type AccountData = (); |
| 157 | + // type OnNewAccount = (); |
| 158 | + // type OnKilledAccount = (); |
| 159 | + // type SystemWeightInfo = (); |
| 160 | + // type SS58Prefix = (); |
| 161 | + // type Version = (); |
| 162 | + // type BlockWeights = (); |
| 163 | + // type BlockLength = (); |
| 164 | + // type DbWeight = (); |
| 165 | + |
| 166 | + // you could still overwrite any of them if desired. |
| 167 | + type SS58Prefix = frame_support::traits::ConstU16<456>; |
| 168 | + } |
| 169 | + |
| 170 | + // Similarly, we use the defaults provided by own crate as well. |
| 171 | + use pallet::config_preludes::TestDefaultConfig; |
| 172 | + #[derive_impl(TestDefaultConfig as pallet::DefaultConfig)] |
| 173 | + impl crate::pallet::Config for Test { |
| 174 | + // These two both cannot have defaults. |
| 175 | + type RuntimeEvent = RuntimeEvent; |
| 176 | + // Note that the default account-id type in |
| 177 | + // `frame_system::config_preludes::TestDefaultConfig` is `u64`. |
| 178 | + type CannotHaveDefault = frame_support::traits::ConstU64<1>; |
| 179 | + |
| 180 | + type OverwrittenDefaultValue = frame_support::traits::ConstU32<678>; |
| 181 | + type OverwrittenDefaultType = u128; |
| 182 | + } |
| 183 | + |
| 184 | + #[test] |
| 185 | + fn it_works() { |
| 186 | + use frame_support::traits::Get; |
| 187 | + use pallet::{Config, DefaultConfig}; |
| 188 | + |
| 189 | + // assert one of the value types that is not overwritten. |
| 190 | + assert_eq!( |
| 191 | + <<Test as Config>::WithDefaultValue as Get<u32>>::get(), |
| 192 | + <<TestDefaultConfig as DefaultConfig>::WithDefaultValue as Get<u32>>::get() |
| 193 | + ); |
| 194 | + |
| 195 | + // assert one of the value types that is overwritten. |
| 196 | + assert_eq!(<<Test as Config>::OverwrittenDefaultValue as Get<u32>>::get(), 678u32); |
| 197 | + |
| 198 | + // assert one of the types that is not overwritten. |
| 199 | + assert_eq!( |
| 200 | + std::any::TypeId::of::<<Test as Config>::WithDefaultType>(), |
| 201 | + std::any::TypeId::of::<<TestDefaultConfig as DefaultConfig>::WithDefaultType>() |
| 202 | + ); |
| 203 | + |
| 204 | + // assert one of the types that is overwritten. |
| 205 | + assert_eq!( |
| 206 | + std::any::TypeId::of::<<Test as Config>::OverwrittenDefaultType>(), |
| 207 | + std::any::TypeId::of::<u128>() |
| 208 | + ) |
| 209 | + } |
| 210 | +} |
0 commit comments