|
| 1 | +//! # Template Pallet |
| 2 | +//! |
| 3 | +//! A pallet with minimal functionality to help developers understand the essential components of |
| 4 | +//! writing a FRAME pallet. It is typically used in beginner tutorials or in Substrate template |
| 5 | +//! nodes as a starting point for creating a new pallet and **not meant to be used in production**. |
| 6 | +//! |
| 7 | +//! ## Overview |
| 8 | +//! |
| 9 | +//! This template pallet contains basic examples of: |
| 10 | +//! - declaring a storage item that stores a single `u32` value |
| 11 | +//! - declaring and using events |
| 12 | +//! - declaring and using errors |
| 13 | +//! - a dispatchable function that allows a user to set a new value to storage and emits an event |
| 14 | +//! upon success |
| 15 | +//! - another dispatchable function that causes a custom error to be thrown |
| 16 | +//! |
| 17 | +//! Each pallet section is annotated with an attribute using the `#[pallet::...]` procedural macro. |
| 18 | +//! This macro generates the necessary code for a pallet to be aggregated into a FRAME runtime. |
| 19 | +//! |
| 20 | +//! Learn more about FRAME macros [here](https://docs.substrate.io/reference/frame-macros/). |
| 21 | +//! |
| 22 | +//! ### Pallet Sections |
| 23 | +//! |
| 24 | +//! The pallet sections in this template are: |
| 25 | +//! |
| 26 | +//! - A **configuration trait** that defines the types and parameters which the pallet depends on |
| 27 | +//! (denoted by the `#[pallet::config]` attribute). See: [`Config`]. |
| 28 | +//! - A **means to store pallet-specific data** (denoted by the `#[pallet::storage]` attribute). |
| 29 | +//! See: [`storage_types`]. |
| 30 | +//! - A **declaration of the events** this pallet emits (denoted by the `#[pallet::event]` |
| 31 | +//! attribute). See: [`Event`]. |
| 32 | +//! - A **declaration of the errors** that this pallet can throw (denoted by the `#[pallet::error]` |
| 33 | +//! attribute). See: [`Error`]. |
| 34 | +//! - A **set of dispatchable functions** that define the pallet's functionality (denoted by the |
| 35 | +//! `#[pallet::call]` attribute). See: [`dispatchables`]. |
| 36 | +//! |
| 37 | +//! Run `cargo doc --package pallet-template --open` to view this pallet's documentation. |
| 38 | +
|
| 39 | +// We make sure this pallet uses `no_std` for compiling to Wasm. |
1 | 40 | #![cfg_attr(not(feature = "std"), no_std)] |
2 | 41 |
|
3 | | -/// Edit this file to define custom logic or remove it if it is not needed. |
4 | | -/// Learn more about FRAME and the core library of Substrate FRAME pallets: |
5 | | -/// <https://docs.substrate.io/reference/frame-pallets/> |
| 42 | +// Re-export pallet items so that they can be accessed from the crate namespace. |
6 | 43 | pub use pallet::*; |
7 | 44 |
|
| 45 | +// FRAME pallets require their own "mock runtimes" to be able to run unit tests. This module |
| 46 | +// contains a mock runtime specific for testing this pallet's functionality. |
8 | 47 | #[cfg(test)] |
9 | 48 | mod mock; |
10 | 49 |
|
| 50 | +// This module contains the unit tests for this pallet. |
| 51 | +// Learn about pallet unit testing here: https://docs.substrate.io/test/unit-testing/ |
11 | 52 | #[cfg(test)] |
12 | 53 | mod tests; |
13 | 54 |
|
| 55 | +// Every callable function or "dispatchable" a pallet exposes must have weight values that correctly |
| 56 | +// estimate a dispatchable's execution time. The benchmarking module is used to calculate weights |
| 57 | +// for each dispatchable and generates this pallet's weight.rs file. Learn more about benchmarking here: https://docs.substrate.io/test/benchmark/ |
14 | 58 | #[cfg(feature = "runtime-benchmarks")] |
15 | 59 | mod benchmarking; |
16 | 60 | pub mod weights; |
17 | 61 | pub use weights::*; |
18 | 62 |
|
| 63 | +// All pallet logic is defined in its own module and must be annotated by the `pallet` attribute. |
19 | 64 | #[frame_support::pallet] |
20 | 65 | pub mod pallet { |
| 66 | + // Import various useful types required by all FRAME pallets. |
21 | 67 | use super::*; |
22 | 68 | use frame_support::pallet_prelude::*; |
23 | 69 | use frame_system::pallet_prelude::*; |
24 | 70 |
|
| 71 | + // The `Pallet` struct serves as a placeholder to implement traits, methods and dispatchables |
| 72 | + // (`Call`s) in this pallet. |
25 | 73 | #[pallet::pallet] |
26 | 74 | pub struct Pallet<T>(_); |
27 | 75 |
|
28 | | - /// Configure the pallet by specifying the parameters and types on which it depends. |
| 76 | + /// The pallet's configuration trait. |
| 77 | + /// |
| 78 | + /// All our types and constants a pallet depends on must be declared here. |
| 79 | + /// These types are defined generically and made concrete when the pallet is declared in the |
| 80 | + /// `runtime/src/lib.rs` file of your chain. |
29 | 81 | #[pallet::config] |
30 | 82 | pub trait Config: frame_system::Config { |
31 | | - /// Because this pallet emits events, it depends on the runtime's definition of an event. |
| 83 | + /// The overarching runtime event type. |
32 | 84 | type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; |
33 | | - /// Type representing the weight of this pallet |
| 85 | + /// A type representing the weights required by the dispatchables of this pallet. |
34 | 86 | type WeightInfo: WeightInfo; |
35 | 87 | } |
36 | 88 |
|
37 | | - // The pallet's runtime storage items. |
38 | | - // https://docs.substrate.io/main-docs/build/runtime-storage/ |
| 89 | + /// A storage item for this pallet. |
| 90 | + /// |
| 91 | + /// In this template, we are declaring a storage item called `Something` that stores a single |
| 92 | + /// `u32` value. Learn more about runtime storage here: <https://docs.substrate.io/build/runtime-storage/> |
| 93 | + /// The [`getter`] macro generates a function to conveniently retrieve the value from storage. |
39 | 94 | #[pallet::storage] |
40 | 95 | #[pallet::getter(fn something)] |
41 | | - // Learn more about declaring storage items: |
42 | | - // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items |
43 | 96 | pub type Something<T> = StorageValue<_, u32>; |
44 | 97 |
|
45 | | - // Pallets use events to inform users when important changes are made. |
46 | | - // https://docs.substrate.io/main-docs/build/events-errors/ |
| 98 | + /// Events that functions in this pallet can emit. |
| 99 | + /// |
| 100 | + /// Events are a simple means of indicating to the outside world (such as dApps, chain explorers |
| 101 | + /// or other users) that some notable update in the runtime has occurred. In a FRAME pallet, the |
| 102 | + /// documentation for each event field and its parameters is added to a node's metadata so it |
| 103 | + /// can be used by external interfaces or tools. |
| 104 | + /// |
| 105 | + /// The `generate_deposit` macro generates a function on `Pallet` called `deposit_event` which |
| 106 | + /// will convert the event type of your pallet into `RuntimeEvent` (declared in the pallet's |
| 107 | + /// [`Config`] trait) and deposit it using [`frame_system::Pallet::deposit_event`]. |
47 | 108 | #[pallet::event] |
48 | 109 | #[pallet::generate_deposit(pub(super) fn deposit_event)] |
49 | 110 | pub enum Event<T: Config> { |
50 | | - /// Event documentation should end with an array that provides descriptive names for event |
51 | | - /// parameters. [something, who] |
52 | | - SomethingStored { something: u32, who: T::AccountId }, |
| 111 | + /// A user has successfully set a new value. |
| 112 | + SomethingStored { |
| 113 | + /// The new value set. |
| 114 | + something: u32, |
| 115 | + /// The account who set the new value. |
| 116 | + who: T::AccountId, |
| 117 | + }, |
53 | 118 | } |
54 | 119 |
|
55 | | - // Errors inform users that something went wrong. |
| 120 | + /// Errors that can be returned by this pallet. |
| 121 | + /// |
| 122 | + /// Errors tell users that something went wrong so it's important that their naming is |
| 123 | + /// informative. Similar to events, error documentation is added to a node's metadata so it's |
| 124 | + /// equally important that they have helpful documentation associated with them. |
| 125 | + /// |
| 126 | + /// This type of runtime error can be up to 4 bytes in size should you want to return additional |
| 127 | + /// information. |
56 | 128 | #[pallet::error] |
57 | 129 | pub enum Error<T> { |
58 | | - /// Error names should be descriptive. |
| 130 | + /// The value retrieved was `None` as no value was previously set. |
59 | 131 | NoneValue, |
60 | | - /// Errors should have helpful documentation associated with them. |
| 132 | + /// There was an attempt to increment the value in storage over `u32::MAX`. |
61 | 133 | StorageOverflow, |
62 | 134 | } |
63 | 135 |
|
64 | | - // Dispatchable functions allows users to interact with the pallet and invoke state changes. |
65 | | - // These functions materialize as "extrinsics", which are often compared to transactions. |
66 | | - // Dispatchable functions must be annotated with a weight and must return a DispatchResult. |
| 136 | + /// The pallet's dispatchable functions ([`Call`]s). |
| 137 | + /// |
| 138 | + /// Dispatchable functions allows users to interact with the pallet and invoke state changes. |
| 139 | + /// These functions materialize as "extrinsics", which are often compared to transactions. |
| 140 | + /// They must always return a `DispatchResult` and be annotated with a weight and call index. |
| 141 | + /// |
| 142 | + /// The [`call_index`] macro is used to explicitly |
| 143 | + /// define an index for calls in the [`Call`] enum. This is useful for pallets that may |
| 144 | + /// introduce new dispatchables over time. If the order of a dispatchable changes, its index |
| 145 | + /// will also change which will break backwards compatibility. |
| 146 | + /// |
| 147 | + /// The [`weight`] macro is used to assign a weight to each call. |
67 | 148 | #[pallet::call] |
68 | 149 | impl<T: Config> Pallet<T> { |
69 | | - /// An example dispatchable that takes a singles value as a parameter, writes the value to |
70 | | - /// storage and emits an event. This function must be dispatched by a signed extrinsic. |
| 150 | + /// An example dispatchable that takes a single u32 value as a parameter, writes the value |
| 151 | + /// to storage and emits an event. |
| 152 | + /// |
| 153 | + /// It checks that the _origin_ for this call is _Signed_ and returns a dispatch |
| 154 | + /// error if it isn't. Learn more about origins here: <https://docs.substrate.io/build/origins/> |
71 | 155 | #[pallet::call_index(0)] |
72 | 156 | #[pallet::weight(T::WeightInfo::do_something())] |
73 | 157 | pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult { |
74 | 158 | // Check that the extrinsic was signed and get the signer. |
75 | | - // This function will return an error if the extrinsic is not signed. |
76 | | - // https://docs.substrate.io/main-docs/build/origins/ |
77 | 159 | let who = ensure_signed(origin)?; |
78 | 160 |
|
79 | 161 | // Update storage. |
80 | | - <Something<T>>::put(something); |
| 162 | + Something::<T>::put(something); |
81 | 163 |
|
82 | 164 | // Emit an event. |
83 | 165 | Self::deposit_event(Event::SomethingStored { something, who }); |
84 | | - // Return a successful DispatchResultWithPostInfo |
| 166 | + |
| 167 | + // Return a successful `DispatchResult` |
85 | 168 | Ok(()) |
86 | 169 | } |
87 | 170 |
|
88 | 171 | /// An example dispatchable that may throw a custom error. |
| 172 | + /// |
| 173 | + /// It checks that the caller is a signed origin and reads the current value from the |
| 174 | + /// `Something` storage item. If a current value exists, it is incremented by 1 and then |
| 175 | + /// written back to storage. |
| 176 | + /// |
| 177 | + /// ## Errors |
| 178 | + /// |
| 179 | + /// The function will return an error under the following conditions: |
| 180 | + /// |
| 181 | + /// - If no value has been set ([`Error::NoneValue`]) |
| 182 | + /// - If incrementing the value in storage causes an arithmetic overflow |
| 183 | + /// ([`Error::StorageOverflow`]) |
89 | 184 | #[pallet::call_index(1)] |
90 | 185 | #[pallet::weight(T::WeightInfo::cause_error())] |
91 | 186 | pub fn cause_error(origin: OriginFor<T>) -> DispatchResult { |
92 | 187 | let _who = ensure_signed(origin)?; |
93 | 188 |
|
94 | 189 | // Read a value from storage. |
95 | | - match <Something<T>>::get() { |
| 190 | + match Pallet::<T>::something() { |
96 | 191 | // Return an error if the value has not been set. |
97 | 192 | None => Err(Error::<T>::NoneValue.into()), |
98 | 193 | Some(old) => { |
99 | | - // Increment the value read from storage; will error in the event of overflow. |
| 194 | + // Increment the value read from storage. This will cause an error in the event |
| 195 | + // of overflow. |
100 | 196 | let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?; |
101 | 197 | // Update the value in storage with the incremented result. |
102 | | - <Something<T>>::put(new); |
| 198 | + Something::<T>::put(new); |
103 | 199 | Ok(()) |
104 | 200 | }, |
105 | 201 | } |
|
0 commit comments