Newer
Older
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// helper function on `Pallet` that handles deposit events.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// NOTE: For instantiable pallets, the event must be generic over `T` and `I`.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::generate_deposit`](`frame_support::pallet_macros::generate_deposit`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Storage: `#[pallet::storage]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::storage]` attribute lets you define some abstract storage inside of runtime
/// storage and also set its metadata. This attribute can be used multiple times.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item should be defined as:
///
/// ```ignore
/// #[pallet::storage]
/// #[pallet::getter(fn $getter_name)] // optional
/// $vis type $StorageName<$some_generic> $optional_where_clause
/// = $StorageType<$generic_name = $some_generics, $other_name = $some_other, ...>;
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// or with unnamed generic:
///
/// ```ignore
/// #[pallet::storage]
/// #[pallet::getter(fn $getter_name)] // optional
/// $vis type $StorageName<$some_generic> $optional_where_clause
/// = $StorageType<_, $some_generics, ...>;
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
/// I.e. it must be a type alias, with generics: `T` or `T: Config`. The aliased type must be
/// one of [`StorageValue`](`pallet_prelude::StorageValue`),
/// [`StorageMap`](`pallet_prelude::StorageMap`) or
/// [`StorageDoubleMap`](`pallet_prelude::StorageDoubleMap`). The generic arguments of the
/// storage type can be given in two manners: named and unnamed. For named generic arguments,
/// the name for each argument should match the name defined for it on the storage struct:
/// * [`StorageValue`](`pallet_prelude::StorageValue`) expects `Value` and optionally
/// `QueryKind` and `OnEmpty`,
/// * [`StorageMap`](`pallet_prelude::StorageMap`) expects `Hasher`, `Key`, `Value` and
/// optionally `QueryKind` and `OnEmpty`,
/// * [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`) expects `Hasher`, `Key`,
/// `Value` and optionally `QueryKind` and `OnEmpty`,
/// * [`StorageDoubleMap`](`pallet_prelude::StorageDoubleMap`) expects `Hasher1`, `Key1`,
/// `Hasher2`, `Key2`, `Value` and optionally `QueryKind` and `OnEmpty`.
///
/// For unnamed generic arguments: Their first generic must be `_` as it is replaced by the
/// macro and other generic must declared as a normal generic type declaration.
///
/// The `Prefix` generic written by the macro is generated using
/// `PalletInfo::name::<Pallet<..>>()` and the name of the storage type. E.g. if runtime names
/// the pallet "MyExample" then the storage `type Foo<T> = ...` should use the prefix:
/// `Twox128(b"MyExample") ++ Twox128(b"Foo")`.
///
/// For the [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`) variant, the `Prefix`
/// also implements
/// [`CountedStorageMapInstance`](`frame_support::storage::types::CountedStorageMapInstance`).
/// It also associates a [`CounterPrefix`](`pallet_prelude::CounterPrefix'), which is
/// implemented the same as above, but the storage prefix is prepend with `"CounterFor"`. E.g.
/// if runtime names the pallet "MyExample" then the storage `type Foo<T> =
/// CountedStorageaMap<...>` will store its counter at the prefix: `Twox128(b"MyExample") ++
/// Twox128(b"CounterForFoo")`.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::storage]
/// pub(super) type MyStorage<T> = StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// In this case the final prefix used by the map is `Twox128(b"MyExample") ++
/// Twox128(b"OtherName")`.
///
/// Also see [`pallet::storage`](`frame_support::pallet_macros::storage`)
///
/// ## `#[pallet::getter(fn $my_getter_fn_name)]` (optional)
///
/// The optional attribute `#[pallet::getter(fn $my_getter_fn_name)]` allows you to define a
/// getter function on `Pallet`.
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::getter`](`frame_support::pallet_macros::getter`)
///
/// ## `#[pallet::storage_prefix = "SomeName"]` (optional)
///
/// The optional attribute `#[pallet::storage_prefix = "SomeName"]` allows you to define the
/// storage prefix to use, see how `Prefix` generic is implemented above. This is helpful if
/// you wish to rename the storage field but don't want to perform a migration.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::storage]
/// #[pallet::storage_prefix = "foo"]
/// #[pallet::getter(fn my_storage)]
/// pub(super) type MyStorage<T> = StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// or
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::storage]
/// #[pallet::getter(fn my_storage)]
/// pub(super) type MyStorage<T> = StorageMap<_, Blake2_128Concat, u32, u32>;
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::storage_prefix`](`frame_support::pallet_macros::storage_prefix`)
///
/// ## `#[pallet::unbounded]` (optional)
///
/// The optional attribute `#[pallet::unbounded]` declares the storage as unbounded. When
/// implementating the storage info (when `#[pallet::generate_storage_info]` is specified on
/// the pallet struct placeholder), the size of the storage will be declared as unbounded. This
/// can be useful for storage which can never go into PoV (Proof of Validity).
///
/// Also see [`pallet::unbounded`](`frame_support::pallet_macros::unbounded`)
///
/// ## `#[pallet::whitelist_storage]` (optional)
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The optional attribute `#[pallet::whitelist_storage]` will declare the storage as
/// whitelisted from benchmarking.
///
/// See
/// [`pallet::whitelist_storage`](frame_support::pallet_macros::whitelist_storage)
/// for more info.
///
/// ## `#[cfg(..)]` (for storage)
/// The optional attributes `#[cfg(..)]` allow conditional compilation for the storage.
///
/// E.g:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[cfg(feature = "my-feature")]
/// #[pallet::storage]
/// pub(super) type MyStorage<T> = StorageValue<Value = u32>;
/// All the `cfg` attributes are automatically copied to the items generated for the storage,
/// i.e. the getter, storage prefix, and the metadata element etc.
/// Any type placed as the `QueryKind` parameter must implement
/// [`frame_support::storage::types::QueryKindTrait`]. There are 3 implementations of this
/// trait by default:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// 1. [`OptionQuery`](`frame_support::storage::types::OptionQuery`), the default `QueryKind`
/// used when this type parameter is omitted. Specifying this as the `QueryKind` would cause
/// storage map APIs that return a `QueryKind` to instead return an [`Option`], returning
/// `Some` when a value does exist under a specified storage key, and `None` otherwise.
/// 2. [`ValueQuery`](`frame_support::storage::types::ValueQuery`) causes storage map APIs that
/// return a `QueryKind` to instead return the value type. In cases where a value does not
/// exist under a specified storage key, the `OnEmpty` type parameter on `QueryKindTrait` is
/// used to return an appropriate value.
/// 3. [`ResultQuery`](`frame_support::storage::types::ResultQuery`) causes storage map APIs
/// that return a `QueryKind` to instead return a `Result<T, E>`, with `T` being the value
/// type and `E` being the pallet error type specified by the `#[pallet::error]` attribute.
/// In cases where a value does not exist under a specified storage key, an `Err` with the
/// specified pallet error variant is returned.
/// NOTE: If the `QueryKind` generic parameter is still generic at this stage or is using some
/// type alias then the generation of the getter might fail. In this case the getter can be
/// implemented manually.
/// 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.
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// ## Macro expansion
/// For each storage item the macro generates a struct named
/// `_GeneratedPrefixForStorage$NameOfStorage`, and implements
/// [`StorageInstance`](traits::StorageInstance) on it using the pallet and storage name. It
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// then uses it as the first generic of the aliased type. For
/// [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`),
/// [`CountedStorageMapInstance`](`frame_support::storage::types::CountedStorageMapInstance`)
/// is implemented, and another similar struct is generated.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// For a named generic, the macro will reorder the generics, and remove the names.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The macro implements the function `storage_metadata` on the `Pallet` implementing the
/// metadata for all storage items based on their kind:
/// * 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 key's type is copied into the metadata
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// * for a storage double map, the type of the values, and the types of `key1` and `key2` are
/// copied into the metadata.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Type value: `#[pallet::type_value]` (optional)
///
/// The `#[pallet::type_value]` attribute lets you define a struct implementing the
/// [`Get`](crate::traits::Get) trait to ease use of storage types. This attribute is meant to
/// be used alongside [`#[pallet::storage]`](#storage-palletstorage-optional) to define a
/// storage's default value. This attribute can be used multiple times.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item must be defined as:
///
/// ```ignore
/// #[pallet::type_value]
/// fn $MyDefaultName<$some_generic>() -> $default_type $optional_where_clause { $expr }
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// I.e.: a function definition with generics none or `T: Config` and a returned type.
///
/// E.g.:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::type_value]
/// fn MyDefault<T: Config>() -> T::Balance { 3.into() }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::type_value`](`frame_support::pallet_macros::type_value`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Genesis config: `#[pallet::genesis_config]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::genesis_config]` attribute allows you to define the genesis configuration
/// for the pallet.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item is defined as either an enum or a struct. It needs to be public and implement the
/// trait [`GenesisBuild`](`traits::GenesisBuild`) with
/// [`#[pallet::genesis_build]`](#genesis-build-palletgenesis_build-optional). The type
/// generics are constrained to be either none, or `T` or `T: Config`.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::genesis_config]
/// pub struct GenesisConfig<T: Config> {
/// _myfield: BalanceOf<T>,
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::genesis_config`](`frame_support::pallet_macros::genesis_config`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Genesis build: `#[pallet::genesis_build]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::genesis_build]` attribute allows you to define how `genesis_configuration`
/// is built. This takes as input the `GenesisConfig` type (as `self`) and constructs the
/// pallet's initial state.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The impl must be defined as:
///
/// ```ignore
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig<$maybe_generics> {
/// fn build(&self) { $expr }
/// }
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// I.e. a trait implementation with generic `T: Config`, of trait `GenesisBuild<T>` on
/// type `GenesisConfig` with generics none or `T`.
///
/// E.g.:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// fn build(&self) {}
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::genesis_build`](`frame_support::pallet_macros::genesis_build`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Inherent: `#[pallet::inherent]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::inherent]` attribute allows the pallet to provide some
/// [inherent](https://docs.substrate.io/fundamentals/transaction-types/#inherent-transactions).
/// An inherent is some piece of data that is inserted by a block authoring node at block
/// creation time and can either be accepted or rejected by validators based on whether the
/// data falls within an acceptable range.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The most common inherent is the `timestamp` that is inserted into every block. Since there
/// is no way to validate timestamps, validators simply check that the timestamp reported by
/// the block authoring node falls within an acceptable range.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item must be defined as:
///
/// ```ignore
/// #[pallet::inherent]
/// impl<T: Config> ProvideInherent for Pallet<T> {
/// // ... regular trait implementation
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// I.e. a trait implementation with bound `T: Config`, of trait
/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`) for type `Pallet<T>`, and some
/// optional where clause.
///
/// Also see [`pallet::inherent`](`frame_support::pallet_macros::inherent`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Validate unsigned: `#[pallet::validate_unsigned]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::validate_unsigned]` attribute allows the pallet to validate some unsigned
/// transaction:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item must be defined as:
///
/// ```ignore
/// #[pallet::validate_unsigned]
/// impl<T: Config> ValidateUnsigned for Pallet<T> {
/// // ... regular trait implementation
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// I.e. a trait implementation with bound `T: Config`, of trait
/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) for type `Pallet<T>`, and some
/// optional where clause.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// NOTE: There is also the [`sp_runtime::traits::SignedExtension`] trait that can be used to
/// add some specific logic for transaction validation.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::validate_unsigned`](`frame_support::pallet_macros::validate_unsigned`)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Origin: `#[pallet::origin]` (optional)
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// The `#[pallet::origin]` attribute allows you to define some origin for the pallet.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Item must be either a type alias, an enum, or a struct. It needs to be public.
///
/// E.g.:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
///
/// ```ignore
/// #[pallet::origin]
/// pub struct Origin<T>(PhantomData<(T)>);
/// ```
///
/// **WARNING**: modifying origin changes the outer runtime origin. This outer runtime origin
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// can be stored on-chain (e.g. in `pallet-scheduler`), thus any change must be done with care
/// as it might require some migration.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// NOTE: for instantiable pallets, the origin must be generic over `T` and `I`.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Also see [`pallet::origin`](`frame_support::pallet_macros::origin`)
/// # Composite enum `#[pallet::composite_enum]` (optional)
/// The `#[pallet::composite_enum]` attribute allows you to define an enum on the pallet which
/// will then instruct `construct_runtime` to amalgamate all similarly-named enums from other
/// pallets into an aggregate enum. This is similar in principle with how the aggregate enum is
/// generated for `#[pallet::event]` or `#[pallet::error]`.
///
/// The item tagged with `#[pallet::composite_enum]` MUST be an enum declaration, and can ONLY
/// be the following identifiers: `FreezeReason`, `HoldReason`, `LockId` or `SlashReason`.
/// Custom identifiers are not supported.
///
/// NOTE: For ease of usage, when no `#[derive]` attributes are detected, the
/// `#[pallet::composite_enum]` attribute will automatically derive the following traits for
/// the enum:
///
/// ```ignore
/// Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo,
/// RuntimeDebug
/// ```
///
/// The inverse is also true: if there are any #[derive] attributes present for the enum, then
/// the attribute will not automatically derive any of the traits described above.
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # General notes on instantiable pallets
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// An instantiable pallet is one where Config is generic, i.e. `Config<I>`. This allows
/// runtime to implement multiple instances of the pallet, by using different types for the
/// generic. This is the sole purpose of the generic `I`, but because
/// [`PalletInfo`](`traits::PalletInfo`) requires the `Pallet` placeholder to be static, it is
/// important to bound by `'static` whenever [`PalletInfo`](`traits::PalletInfo`) can be used.
/// Additionally, in order to make an instantiable pallet usable as a regular pallet without an
/// instance, it is important to bound by `= ()` on every type.
///
/// Thus impl bound looks like `impl<T: Config<I>, I: 'static>`, and types look like
/// `SomeType<T, I=()>` or `SomeType<T: Config<I>, I: 'static = ()>`.
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Example of a non-instantiable pallet
/// 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!();
/// }
/// }
///
/// // 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";
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Example of an instantiable pallet
/// #[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 extra_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 {
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
/// 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>;
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
///
/// #[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!();
/// }
/// }
///
/// // 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";
/// }
/// ```
///
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # 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`
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// 2. Generate the template upgrade for the pallet provided by `decl_storage` with the
/// environment variable `PRINT_PALLET_UPGRADE`: `PRINT_PALLET_UPGRADE=1 cargo check -p
/// my_pallet`. This template can be used as it contains all information for storages,
/// genesis config and genesis build.
/// 3. Reorganize the pallet to have the trait `Config`, `decl_*` macros,
/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`),
/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`), and 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
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// * all const in `decl_module` to [`#[pallet::constant]`](#palletconstant)
/// * add the 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> {
/// }
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// and write inside `on_initialize`, `on_finalize`, `on_runtime_upgrade`,
/// `offchain_worker`, and `integrity_test`.
///
/// then write:
/// ```ignore
/// #[pallet::call]
/// }
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// 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]`](#palletcompact-some_arg-some_type)
/// - `#[weight = ..]` must now be written [`#[pallet::weight(..)]`](#palletweightexpr)
///
/// 7. **migrate event**: rewrite as a simple enum with the attribute
/// [`#[pallet::event]`](#event-palletevent-optional), use [`#[pallet::generate_deposit($vis
/// fn deposit_event)]`](#event-palletevent-optional) to generate `deposit_event`,
/// 8. **migrate error**: rewrite it with attribute
/// [`#[pallet::error]`](#error-palleterror-optional).
/// 9. **migrate storage**: `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
/// }
/// }
/// ```
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// for each storage, if it contains `config(..)` then add fields, and make it 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 storage if it contains `build(..)` then add the
/// logic to `genesis_build`.
///
/// NOTE: within `decl_storage`: the individual config is executed first, followed by the
/// build and finally the `add_extra_genesis` build.
///
/// Once this is done you can migrate storages individually, a few notes:
/// - for private storage use `pub(crate) type ` or `pub(super) type` or nothing,
/// - for storages with `get(fn ..)` use [`#[pallet::getter(fn
/// ...)]`](#palletgetterfn-my_getter_fn_name-optional)
/// - for storages 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 storages 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>;
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// NOTE: `decl_storage` also generates the functions `assimilate_storage` and
/// `build_storage` directly on `GenesisConfig`, and these are sometimes used in tests.
/// In order not to break they can be implemented manually, one can implement those
/// functions by calling the `GenesisBuild` implementation.
/// 10. **migrate origin**: move the origin to the pallet module to be under a
/// [`#[pallet::origin]`](#origin-palletorigin-optional) attribute
/// 11. **migrate validate_unsigned**: move the
/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) implementation to the pallet
/// module under a
/// [`#[pallet::validate_unsigned]`](#validate-unsigned-palletvalidate_unsigned-optional)
/// attribute
/// 12. **migrate provide_inherent**: move the
/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`) implementation to the pallet
/// module under a [`#[pallet::inherent]`](#inherent-palletinherent-optional) attribute
/// 13. rename the usage of `Module` to `Pallet` inside the crate.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// 14. migration is done, now double check the migration with the checking migration
/// guidelines shown below.
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// # Checking upgrade guidelines:
/// * compare metadata. Use [subsee](https://github.com/ascjones/subsee) to fetch the metadata
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// 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:
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// * `Origin` was moved inside the macro under
/// [`#[pallet::origin]`](#origin-palletorigin-optional) if it exists
/// * [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) was moved inside the macro
/// under
/// [`#[pallet::validate_unsigned)]`](#validate-unsigned-palletvalidate_unsigned-optional)
/// if it exists
/// * [`ProvideInherent`](`pallet_prelude::ProvideInherent`) was moved inside the macro
/// under [`#[pallet::inherent)]`](#inherent-palletinherent-optional) if it exists
/// * `on_initialize` / `on_finalize` / `on_runtime_upgrade` / `offchain_worker` were moved
/// to the `Hooks` implementation
/// * storages with `config(..)` were converted to `GenesisConfig` field, and their default
/// is `= $expr;` if the storage has a default value
/// * storages with `build($expr)` or `config(..)` were built in `GenesisBuild::build`
/// * `add_extra_genesis` fields were converted to `GenesisConfig` field with their correct
/// default if specified
/// * `add_extra_genesis` build was written into `GenesisBuild::build`
/// * storage items defined with [`pallet`] use the name of the pallet provided by
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// [`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 metadata. Thus, ensuring the metadata
/// hasn't changed ensures 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;
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
/// Contains macro stubs for all of the pallet:: macros
pub mod pallet_macros {
pub use frame_support_procedural::{
call_index, compact, composite_enum, config, constant,
disable_frame_system_supertrait_check, error, event, extra_constants, generate_deposit,
generate_store, genesis_build, genesis_config, getter, hooks, inherent, origin, storage,
storage_prefix, storage_version, type_value, unbounded, validate_unsigned, weight,
whitelist_storage,
![Sam Johnson Sam Johnson's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Sam Johnson
committed
};
}
// Generate a macro that will enable/disable code based on `std` feature being active.
sp_core::generate_feature_enabled_macro!(std_enabled, feature = "std", $);