Newer
Older
/// * `#[cfg(feature = "std")]`
///
/// Macro will implement `sp_runtime::BuildModuleGenesisStorage` using `()` as second generic
/// for non-instantiable pallets.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
///
/// # Inherent: `#[pallet::inherent]` optional
///
/// Allow the pallet to provide some inherent:
///
/// Item is defined as:
/// ```ignore
/// #[pallet::inherent]
/// impl<T: Config> ProvideInherent for Pallet<T> {
/// // ... regular trait implementation
/// }
/// ```
/// I.e. a trait implementation with bound `T: Config`, of trait `ProvideInherent` for type
/// `Pallet<T>`, and some optional where clause.
///
/// ### Macro expansion
///
/// Macro make currently no use of this information, but it might use this information in the
/// future to give information directly to construct_runtime.
///
/// # Validate unsigned: `#[pallet::validate_unsigned]` optional
///
/// Allow the pallet to validate some unsigned transaction:
///
/// Item is defined as:
/// ```ignore
/// #[pallet::validate_unsigned]
/// impl<T: Config> ValidateUnsigned for Pallet<T> {
/// // ... regular trait implementation
/// }
/// ```
/// I.e. a trait implementation with bound `T: Config`, of trait `ValidateUnsigned` for type
/// `Pallet<T>`, and some optional where clause.
///
/// NOTE: There is also `sp_runtime::traits::SignedExtension` that can be used to add some
/// specific logic for transaction validation.
///
/// ### Macro expansion
///
/// Macro make currently no use of this information, but it might use this information in the
/// future to give information directly to construct_runtime.
///
/// # Origin: `#[pallet::origin]` optional
///
/// Allow to define some origin for the pallet.
///
/// Item must be either a type alias or an enum or a struct. It needs to be public.
///
/// E.g.:
/// ```ignore
/// #[pallet::origin]
/// pub struct Origin<T>(PhantomData<(T)>);
/// ```
///
/// **WARNING**: modifying origin changes the outer runtime origin. This outer runtime origin
/// can be stored on-chain (e.g. in pallet-scheduler), thus any change must be done with care
/// as it might require some migration.
///
/// NOTE: for instantiable pallet, origin must be generic over T and I.
///
/// # General notes on instantiable pallet
///
/// An instantiable pallet is one where Config is generic, i.e. `Config<I>`. This allow runtime
/// to implement multiple instance of the pallet, by using different type for the generic.
/// This is the sole purpose of the generic `I`.
/// But because `PalletInfo` requires `Pallet` placeholder to be static it is important to
/// bound `'static` whenever `PalletInfo` can be used.
/// And in order to have instantiable pallet usable as a regular pallet without instance, it is
/// important to bound `= ()` on every types.
///
/// Thus impl bound look like `impl<T: Config<I>, I: 'static>`, and types look like
/// `SomeType<T, I=()>` or `SomeType<T: Config<I>, I: 'static = ()>`.
///
/// # Example for pallet without instance.
///
/// ```
/// pub use pallet::*; // reexport in crate namespace for `construct_runtime!`
///
/// #[frame_support::pallet]
/// // NOTE: The name of the pallet is provided by `construct_runtime` and is used as
/// // the unique identifier for the pallet's storage. It is not defined in the pallet itself.
/// pub mod pallet {
/// use frame_support::pallet_prelude::*; // Import various types used in the pallet definition
/// use frame_system::pallet_prelude::*; // Import some system helper types.
///
/// type BalanceOf<T> = <T as Config>::Balance;
///
/// // Define the generic parameter of the pallet
/// // The macro parses `#[pallet::constant]` attributes and uses them to generate metadata
/// // for the pallet's constants.
/// #[pallet::config]
/// pub trait Config: frame_system::Config {
/// #[pallet::constant] // put the constant in metadata
/// type MyGetParam: Get<u32>;
/// type Balance: Parameter + MaxEncodedLen + From<u8>;
/// type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// }
///
/// // Define some additional constant to put into the constant metadata.
/// #[pallet::extra_constants]
/// impl<T: Config> Pallet<T> {
/// /// Some description
/// fn exra_constant_name() -> u128 { 4u128 }
/// }
///
/// // Define the pallet struct placeholder, various pallet function are implemented on it.
/// #[pallet::pallet]
/// #[pallet::generate_store(pub(super) trait Store)]
![thiolliere thiolliere's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
thiolliere
committed
/// pub struct Pallet<T>(_);
/// #[pallet::hooks]
/// impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
/// fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
/// unimplemented!();
/// }
///
/// // can implement also: on_finalize, on_runtime_upgrade, offchain_worker, ...
/// // see `Hooks` trait
/// }
///
/// // Declare Call struct and implement dispatchables.
/// //
/// // WARNING: Each parameter used in functions must implement: Clone, Debug, Eq, PartialEq,
/// // Codec.
/// //
/// // The macro parses `#[pallet::compact]` attributes on function arguments and implements
/// // the `Call` encoding/decoding accordingly.
/// #[pallet::call]
/// impl<T: Config> Pallet<T> {
/// /// Doc comment put in metadata
/// #[pallet::weight(0)] // Defines weight for call (function parameters are in scope)
/// origin: OriginFor<T>,
/// ) -> DispatchResultWithPostInfo {
/// let _ = origin;
/// unimplemented!();
/// }
/// }
///
/// // Declare the pallet `Error` enum (this is optional).
/// // The macro generates error metadata using the doc comment on each variant.
/// #[pallet::error]
/// pub enum Error<T> {
/// /// doc comment put into metadata
/// InsufficientProposersBalance,
/// }
///
/// // Declare pallet Event enum (this is optional).
/// //
/// // WARNING: Each type used in variants must implement: Clone, Debug, Eq, PartialEq, Codec.
/// //
/// // The macro generates event metadata, and derive Clone, Debug, Eq, PartialEq and Codec
/// #[pallet::event]
/// // Generate a funciton on Pallet to deposit an event.
/// #[pallet::generate_deposit(pub(super) fn deposit_event)]
/// pub enum Event<T: Config> {
/// /// doc comment put in metadata
/// // `<T as frame_system::Config>::AccountId` is not defined in metadata list, the last
/// // Thus the metadata is `<T as frame_system::Config>::AccountId`.
/// Proposed(<T as frame_system::Config>::AccountId),
/// /// doc
/// // here metadata will be `Balance` as define in metadata list
/// Spending(BalanceOf<T>),
/// // here metadata will be `Other` as define in metadata list
/// Something(u32),
/// }
///
/// // Define a struct which implements `frame_support::traits::Get<T::Balance>` (optional).
/// #[pallet::type_value]
/// pub(super) fn MyDefault<T: Config>() -> T::Balance { 3.into() }
///
/// // Declare a storage item. Any amount of storage items can be declared (optional).
/// //
/// // Is expected either `StorageValue`, `StorageMap` or `StorageDoubleMap`.
/// // The macro generates the prefix type and replaces the first generic `_`.
/// //
/// // The macro expands the metadata for the storage item with the type used:
/// // * for a storage value the type of the value is copied into the metadata
/// // * for a storage map the type of the values and the type of the key is copied into the metadata
/// // * for a storage double map the types of the values and keys are copied into the
/// // metadata.
/// //
/// // NOTE: The generic `Hasher` must implement the `StorageHasher` trait (or the type is not
/// // usable at all). We use [`StorageHasher::METADATA`] for the metadata of the hasher of the
/// // storage item. Thus generic hasher is supported.
/// #[pallet::storage]
/// pub(super) type MyStorageValue<T: Config> =
/// StorageValue<Value = T::Balance, QueryKind = ValueQuery, OnEmpty = MyDefault<T>>;
/// #[pallet::storage]
/// #[pallet::getter(fn my_storage)]
/// #[pallet::storage_prefix = "SomeOtherName"]
/// pub(super) type MyStorage<T> =
/// StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
/// // Declare the genesis config (optional).
/// // The macro accepts either a struct or an enum; it checks that generics are consistent.
/// // Type must implement the `Default` trait.
/// #[pallet::genesis_config]
/// #[derive(Default)]
/// pub struct GenesisConfig {
/// _myfield: u32,
/// }
///
/// // Declare genesis builder. (This is need only if GenesisConfig is declared)
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// fn build(&self) {}
/// }
///
/// // Declare a pallet origin (this is optional).
/// //
/// // The macro accept type alias or struct or enum, it checks generics are consistent.
/// #[pallet::origin]
/// pub struct Origin<T>(PhantomData<T>);
///
/// // Declare validate_unsigned implementation (this is optional).
/// #[pallet::validate_unsigned]
/// impl<T: Config> ValidateUnsigned for Pallet<T> {
/// type Call = Call<T>;
/// fn validate_unsigned(
/// source: TransactionSource,
/// call: &Self::Call
/// ) -> TransactionValidity {
/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
/// }
/// }
///
/// // Declare inherent provider for pallet (this is optional).
/// #[pallet::inherent]
/// impl<T: Config> ProvideInherent for Pallet<T> {
/// type Call = Call<T>;
/// type Error = InherentError;
///
/// const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
///
/// fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
/// unimplemented!();
/// }
///
/// fn is_inherent(_call: &Self::Call) -> bool {
/// unimplemented!();
/// }
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
/// }
///
/// // Regular rust code needed for implementing ProvideInherent trait
///
/// #[derive(codec::Encode, sp_runtime::RuntimeDebug)]
/// #[cfg_attr(feature = "std", derive(codec::Decode))]
/// pub enum InherentError {
/// }
///
/// impl sp_inherents::IsFatalError for InherentError {
/// fn is_fatal_error(&self) -> bool {
/// unimplemented!();
/// }
/// }
///
/// pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall";
/// }
/// ```
///
/// # Example for pallet with instance.
///
/// ```
/// #[frame_support::pallet]
/// pub mod pallet {
/// use frame_support::pallet_prelude::*;
/// use frame_system::pallet_prelude::*;
///
/// type BalanceOf<T, I = ()> = <T as Config<I>>::Balance;
///
/// #[pallet::config]
/// pub trait Config<I: 'static = ()>: frame_system::Config {
/// #[pallet::constant]
/// type MyGetParam: Get<u32>;
/// type Balance: Parameter + MaxEncodedLen + From<u8>;
/// type RuntimeEvent: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// }
///
/// #[pallet::extra_constants]
/// impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// /// Some description
/// fn exra_constant_name() -> u128 { 4u128 }
/// }
///
/// #[pallet::pallet]
/// #[pallet::generate_store(pub(super) trait Store)]
/// pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
///
/// #[pallet::hooks]
/// impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
/// }
///
/// #[pallet::call]
/// impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// /// Doc comment put in metadata
/// #[pallet::weight(0)]
/// pub fn toto(origin: OriginFor<T>, #[pallet::compact] _foo: u32) -> DispatchResultWithPostInfo {
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
/// let _ = origin;
/// unimplemented!();
/// }
/// }
///
/// #[pallet::error]
/// pub enum Error<T, I = ()> {
/// /// doc comment put into metadata
/// InsufficientProposersBalance,
/// }
///
/// #[pallet::event]
/// #[pallet::generate_deposit(pub(super) fn deposit_event)]
/// pub enum Event<T: Config<I>, I: 'static = ()> {
/// /// doc comment put in metadata
/// Proposed(<T as frame_system::Config>::AccountId),
/// /// doc
/// Spending(BalanceOf<T, I>),
/// Something(u32),
/// }
///
/// #[pallet::type_value]
/// pub(super) fn MyDefault<T: Config<I>, I: 'static>() -> T::Balance { 3.into() }
///
/// #[pallet::storage]
/// pub(super) type MyStorageValue<T: Config<I>, I: 'static = ()> =
/// StorageValue<Value = T::Balance, QueryKind = ValueQuery, OnEmpty = MyDefault<T, I>>;
///
/// #[pallet::storage]
/// #[pallet::getter(fn my_storage)]
/// #[pallet::storage_prefix = "SomeOtherName"]
/// pub(super) type MyStorage<T, I = ()> =
/// StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
///
/// #[pallet::genesis_config]
/// #[derive(Default)]
/// pub struct GenesisConfig {
/// _myfield: u32,
/// }
///
/// #[pallet::genesis_build]
/// impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig {
/// fn build(&self) {}
/// }
///
/// #[pallet::origin]
/// pub struct Origin<T, I = ()>(PhantomData<(T, I)>);
///
/// #[pallet::validate_unsigned]
/// impl<T: Config<I>, I: 'static> ValidateUnsigned for Pallet<T, I> {
/// type Call = Call<T, I>;
/// fn validate_unsigned(
/// source: TransactionSource,
/// call: &Self::Call
/// ) -> TransactionValidity {
/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
/// }
/// }
///
/// #[pallet::inherent]
/// impl<T: Config<I>, I: 'static> ProvideInherent for Pallet<T, I> {
/// type Call = Call<T, I>;
/// type Error = InherentError;
///
/// const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
///
/// fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
/// unimplemented!();
/// }
///
/// fn is_inherent(_call: &Self::Call) -> bool {
/// unimplemented!();
/// }
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
/// }
///
/// // Regular rust code needed for implementing ProvideInherent trait
///
/// #[derive(codec::Encode, sp_runtime::RuntimeDebug)]
/// #[cfg_attr(feature = "std", derive(codec::Decode))]
/// pub enum InherentError {
/// }
///
/// impl sp_inherents::IsFatalError for InherentError {
/// fn is_fatal_error(&self) -> bool {
/// unimplemented!();
/// }
/// }
///
/// pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall";
/// }
/// ```
///
/// ## Upgrade guidelines:
///
/// 1. Export the metadata of the pallet for later checks
/// - run your node with the pallet active
/// - query the metadata using the `state_getMetadata` RPC and curl, or use `subsee -p
/// <PALLET_NAME> > meta.json`
/// 2. generate the template upgrade for the pallet provided by decl_storage
/// with environment variable `PRINT_PALLET_UPGRADE`:
/// `PRINT_PALLET_UPGRADE=1 cargo check -p my_pallet` This template can be
/// used as information it contains all information for storages, genesis
/// config and genesis build.
/// 3. reorganize pallet to have trait `Config`, `decl_*` macros, `ValidateUnsigned`,
/// `ProvideInherent`, `Origin` all together in one file. Suggested order:
/// * Config,
/// * decl_module,
/// * decl_event,
/// * decl_error,
/// * decl_storage,
/// * origin,
/// * validate_unsigned,
/// * provide_inherent,
/// so far it should compile and all be correct.
/// 4. start writing the new pallet module
/// ```ignore
/// pub use pallet::*;
///
/// #[frame_support::pallet]
/// pub mod pallet {
/// use frame_support::pallet_prelude::*;
/// use frame_system::pallet_prelude::*;
/// use super::*;
///
/// #[pallet::pallet]
/// #[pallet::generate_store($visibility_of_trait_store trait Store)]
/// // NOTE: if the visibility of trait store is private but you want to make it available
/// // in super, then use `pub(super)` or `pub(crate)` to make it available in crate.
![thiolliere thiolliere's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
thiolliere
committed
/// pub struct Pallet<T>(_);
/// // pub struct Pallet<T, I = ()>(PhantomData<T>); // for instantiable pallet
/// }
/// ```
/// 5. **migrate Config**: move trait into the module with
/// * all const in decl_module to `#[pallet::constant]`
/// * add bound `IsType<<Self as frame_system::Config>::RuntimeEvent>` to `type RuntimeEvent`
/// 7. **migrate decl_module**: write:
/// ```ignore
/// #[pallet::hooks]
/// impl<T: Config> Hooks for Pallet<T> {
/// }
/// ```
/// and write inside
/// `on_initialize`, `on_finalize`, `on_runtime_upgrade`, `offchain_worker`, `integrity_test`.
///
/// then write:
/// ```ignore
/// #[pallet::call]
/// }
/// ```
/// and write inside all the calls in decl_module with a few changes in the signature:
/// - origin must now be written completely, e.g. `origin: OriginFor<T>`
/// - result type must be `DispatchResultWithPostInfo`, you need to write it and also you
/// might
/// need to put `Ok(().into())` at the end or the function.
/// - `#[compact]` must now be written `#[pallet::compact]`
/// - `#[weight = ..]` must now be written `#[pallet::weight(..)]`
///
/// rewrite as a simple enum under with the attribute `#[pallet::event]`,
/// use `#[pallet::generate_deposit($vis fn deposit_event)]` to generate deposit_event,
/// 8. **migrate error**: rewrite it with attribute `#[pallet::error]`.
/// decl_storage provide an upgrade template (see 3.). All storages, genesis config, genesis
/// build and default implementation of genesis config can be taken from it directly.
///
/// Otherwise here is the manual process:
///
/// first migrate the genesis logic. write:
/// ```ignore
/// #[pallet::genesis_config]
/// struct GenesisConfig {
/// // fields of add_extra_genesis
/// }
/// impl Default for GenesisConfig {
/// // type default or default provided for fields
/// }
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// // for instantiable pallet:
/// // `impl<T: Config, I: 'static> GenesisBuild<T, I> for GenesisConfig {
/// fn build() {
/// // The add_extra_genesis build logic
/// }
/// }
/// ```
/// for each storages, if it contains config(..) then add a fields, and make its default to the
/// value in `= ..;` or the type default if none, if it contains no build then also add the
/// logic to build the value.
/// for each storages if it contains build(..) then add the logic to genesis_build.
///
/// NOTE: in decl_storage: is executed first the individual config and build and at the end the
/// add_extra_genesis build
///
/// Once this is done you can migrate storage individually, a few notes:
/// - for private storage use `pub(crate) type ` or `pub(super) type` or nothing,
/// - for storage with `get(fn ..)` use `#[pallet::getter(fn ...)]`
/// - for storage with value being `Option<$something>` make generic `Value` being
/// `$something`
/// and generic `QueryKind` being `OptionQuery` (note: this is default). Otherwise make
/// `Value` the complete value type and `QueryKind` being `ValueQuery`.
/// - for storage with default value: `= $expr;` provide some specific OnEmpty generic. To do
/// so
/// use of `#[pallet::type_value]` to generate the wanted struct to put.
/// example: `MyStorage: u32 = 3u32` would be written:
/// ```ignore
/// #[pallet::type_value] fn MyStorageOnEmpty() -> u32 { 3u32 }
/// #[pallet::storage]
/// pub(super) type MyStorage<T> = StorageValue<_, u32, ValueQuery, MyStorageOnEmpty>;
/// NOTE: `decl_storage` also generates functions `assimilate_storage` and `build_storage`
/// directly on GenesisConfig, those are sometimes used in tests. In order not to break they
/// can be implemented manually, one can implement those functions by calling `GenesisBuild`
/// implementation.
///
/// 10. **migrate origin**: move the origin to the pallet module under `#[pallet::origin]`
/// 11. **migrate validate_unsigned**: move the `ValidateUnsigned` implementation to the pallet
/// module under `#[pallet::validate_unsigned]`
/// 12. **migrate provide_inherent**: move the `ProvideInherent` implementation to the pallet
/// module under `#[pallet::inherent]`
/// 13. rename the usage of `Module` to `Pallet` inside the crate.
/// 14. migration is done, now double check migration with the checking migration guidelines.
///
/// ## Checking upgrade guidelines:
///
/// * compare metadata. Use [subsee](https://github.com/ascjones/subsee) to fetch the metadata
/// and do a diff of the resulting json before and after migration. This checks for:
/// * call, names, signature, docs
/// * event names, docs
/// * error names, docs
/// * storage names, hasher, prefixes, default value
/// * error , error, constant,
/// * manually check that:
/// * `Origin` is moved inside the macro under `#[pallet::origin]` if it exists
/// * `ValidateUnsigned` is moved inside the macro under `#[pallet::validate_unsigned)]` if it
/// exists
/// * `ProvideInherent` is moved inside macro under `#[pallet::inherent)]` if it exists
/// * `on_initialize`/`on_finalize`/`on_runtime_upgrade`/`offchain_worker` are moved to
/// `Hooks`
/// implementation
/// * storages with `config(..)` are converted to `GenesisConfig` field, and their default is
/// `= $expr;` if the storage have default value
/// * storages with `build($expr)` or `config(..)` are built in `GenesisBuild::build`
/// * `add_extra_genesis` fields are converted to `GenesisConfig` field with their correct
/// default if specified
/// * `add_extra_genesis` build is written into `GenesisBuild::build`
/// * storage items defined with [`pallet`] use the name of the pallet provided by
/// [`traits::PalletInfo::name`] as `pallet_prefix` (in `decl_storage`, storage items used the
/// `pallet_prefix` given as input of `decl_storage` with the syntax `as Example`).
/// Thus a runtime using the pallet must be careful with this change.
/// To handle this change:
/// * either ensure that the name of the pallet given to `construct_runtime!` is the same
/// as the name the pallet was giving to `decl_storage`,
/// * or do a storage migration from the old prefix used to the new prefix used.
///
/// NOTE: The prefixes used by storage items are in the metadata. Thus, ensuring the metadata
/// hasn't changed does ensure that the `pallet_prefix`s used by the storage items haven't
/// changed.
///
/// # Notes when macro fails to show proper error message spans:
///
/// Rustc loses span for some macro input. Some tips to fix it:
/// * do not use inner attribute:
/// ```ignore
/// #[pallet]
/// pub mod pallet {
/// //! This inner attribute will make span fail
/// ..
/// }
/// ```
/// * use the newest nightly possible.
pub use frame_support_procedural::pallet;