// This file is part of Bizinikiwi. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: MIT-0 // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. //! # Default Config Pallet Example //! //! A simple example of a FRAME pallet that utilizes [`pezframe_support::derive_impl`] to demonstrate //! the simpler way to implement `Config` trait of pallets. This example only showcases this in a //! `mock.rs` environment, but the same applies to a real runtime as well. //! //! See the source code of [`tests`] for a real examples. //! //! Study the following types: //! //! - [`pallet::DefaultConfig`], and how it differs from [`pallet::Config`]. //! - [`struct@pallet::config_preludes::TestDefaultConfig`] and how it implements //! [`pallet::DefaultConfig`]. //! - Notice how [`pallet::DefaultConfig`] is independent of [`pezframe_system::Config`]. #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; #[pezframe_support::pallet] pub mod pallet { use pezframe_support::pezpallet_prelude::*; /// This pallet is annotated to have a default config. This will auto-generate /// [`DefaultConfig`]. /// /// It will be an identical, but won't have anything that is `#[pallet::no_default]`. #[pallet::config(with_default)] pub trait Config: pezframe_system::Config { /// The overarching task type. This is coming from the runtime, and cannot have a default. /// In general, `Runtime*`-oriented types cannot have a sensible default. #[pallet::no_default] // optional. `RuntimeEvent` is automatically excluded as well. type RuntimeTask: Task; /// An input parameter to this pallet. This value can have a default, because it is not /// reliant on `pezframe_system::Config` or the overarching runtime in any way. type WithDefaultValue: Get; /// Same as [`Config::WithDefaultValue`], but we don't intend to define a default for this /// in our tests below. type OverwrittenDefaultValue: Get; /// An input parameter that relies on `::AccountId`. This can /// too have a default, as long as it is present in `pezframe_system::DefaultConfig`. type CanDeriveDefaultFromSystem: Get; /// We might choose to declare as one that doesn't have a default, for whatever semantical /// reason. #[pallet::no_default] type HasNoDefault: Get; /// Some types can technically have no default, such as those the rely on /// `pezframe_system::Config` but are not present in `pezframe_system::DefaultConfig`. For /// example, a `RuntimeCall` cannot reasonably have a default. #[pallet::no_default] // if we skip this, there will be a compiler error. type CannotHaveDefault: Get; /// Something that is a normal type, with default. type WithDefaultType; /// Same as [`Config::WithDefaultType`], but we don't intend to define a default for this /// in our tests below. type OverwrittenDefaultType; } /// Container for different types that implement [`DefaultConfig`]` of this pallet. pub mod config_preludes { // This will help use not need to disambiguate anything when using `derive_impl`. use super::*; use pezframe_support::derive_impl; /// A type providing default configurations for this pallet in testing environment. pub struct TestDefaultConfig; #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl pezframe_system::DefaultConfig for TestDefaultConfig {} #[pezframe_support::register_default_impl(TestDefaultConfig)] impl DefaultConfig for TestDefaultConfig { type WithDefaultValue = pezframe_support::traits::ConstU32<42>; type OverwrittenDefaultValue = pezframe_support::traits::ConstU32<42>; // `pezframe_system::config_preludes::TestDefaultConfig` declares account-id as u64. type CanDeriveDefaultFromSystem = pezframe_support::traits::ConstU64<42>; type WithDefaultType = u32; type OverwrittenDefaultType = u32; } /// A type providing default configurations for this pallet in another environment. Examples /// could be a teyrchain, or a solochain. /// /// Appropriate derive for `pezframe_system::DefaultConfig` needs to be provided. In this /// example, we simple derive `pezframe_system::config_preludes::TestDefaultConfig` again. pub struct OtherDefaultConfig; #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl pezframe_system::DefaultConfig for OtherDefaultConfig {} #[pezframe_support::register_default_impl(OtherDefaultConfig)] impl DefaultConfig for OtherDefaultConfig { type WithDefaultValue = pezframe_support::traits::ConstU32<66>; type OverwrittenDefaultValue = pezframe_support::traits::ConstU32<66>; type CanDeriveDefaultFromSystem = pezframe_support::traits::ConstU64<42>; type WithDefaultType = u32; type OverwrittenDefaultType = u32; } } #[pallet::pallet] pub struct Pallet(_); #[pallet::event] pub enum Event {} } #[cfg(any(test, doc))] pub mod tests { use super::*; use pezframe_support::{derive_impl, parameter_types}; use pallet::{self as pezpallet_default_config_example, config_preludes::*}; type Block = pezframe_system::mocking::MockBlock; pezframe_support::construct_runtime!( pub enum Runtime { System: pezframe_system, DefaultPallet: pezpallet_default_config_example, } ); #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)] impl pezframe_system::Config for Runtime { // these items are defined by pezframe-system as `no_default`, so we must specify them here. type Block = Block; // all of this is coming from `pezframe_system::config_preludes::TestDefaultConfig`. // type Nonce = u32; // type BlockNumber = u32; // type Hash = pezsp_core::hash::H256; // type Hashing = pezsp_runtime::traits::BlakeTwo256; // type AccountId = u64; // type Lookup = pezsp_runtime::traits::IdentityLookup; // type BlockHashCount = pezframe_support::traits::ConstU32<10>; // type MaxConsumers = pezframe_support::traits::ConstU32<16>; // type AccountData = (); // type OnNewAccount = (); // type OnKilledAccount = (); // type SystemWeightInfo = (); // type SS58Prefix = (); // type Version = (); // type BlockWeights = (); // type BlockLength = (); // type DbWeight = (); // type BaseCallFilter = pezframe_support::traits::Everything; // type BlockHashCount = pezframe_support::traits::ConstU64<10>; // type OnSetCode = (); // These are marked as `#[inject_runtime_type]`. Hence, they are being injected as // types generated by `construct_runtime`. // type RuntimeOrigin = RuntimeOrigin; // type RuntimeCall = RuntimeCall; // type RuntimeEvent = RuntimeEvent; // type PalletInfo = PalletInfo; // you could still overwrite any of them if desired. type SS58Prefix = pezframe_support::traits::ConstU16<456>; } parameter_types! { pub const SomeCall: RuntimeCall = RuntimeCall::System(pezframe_system::Call::::remark { remark: alloc::vec![] }); } #[derive_impl(TestDefaultConfig as pallet::DefaultConfig)] impl pezpallet_default_config_example::Config for Runtime { // This cannot have default. type RuntimeTask = RuntimeTask; type HasNoDefault = pezframe_support::traits::ConstU32<1>; type CannotHaveDefault = SomeCall; type OverwrittenDefaultValue = pezframe_support::traits::ConstU32<678>; type OverwrittenDefaultType = u128; } #[test] fn it_works() { use pezframe_support::traits::Get; use pallet::{Config, DefaultConfig}; // assert one of the value types that is not overwritten. assert_eq!( <::WithDefaultValue as Get>::get(), <::WithDefaultValue as Get>::get() ); // assert one of the value types that is overwritten. assert_eq!(<::OverwrittenDefaultValue as Get>::get(), 678u32); // assert one of the types that is not overwritten. assert_eq!( std::any::TypeId::of::<::WithDefaultType>(), std::any::TypeId::of::<::WithDefaultType>() ); // assert one of the types that is overwritten. assert_eq!( std::any::TypeId::of::<::OverwrittenDefaultType>(), std::any::TypeId::of::() ) } }