pallet_example_kitchensink/lib.rs
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//! # Kitchensink Example Pallet
19//!
20//! **This pallet serves as an example and is not meant to be used in production.**
21//!
22//! The kitchen-sink catalog of the the FRAME macros and their various syntax options.
23//!
24//! This example does not focus on pallet instancing, `dev_mode`, and does nto include any 'where'
25//! clauses on `T`. These will both incur additional complexity to the syntax, but are not discussed
26//! here.
27
28#![cfg_attr(not(feature = "std"), no_std)]
29
30// Re-export pallet items so that they can be accessed from the crate namespace.
31pub use pallet::*;
32
33#[cfg(test)]
34mod tests;
35
36#[cfg(feature = "runtime-benchmarks")]
37mod benchmarking;
38
39#[cfg(feature = "try-runtime")]
40use sp_runtime::TryRuntimeError;
41
42pub mod weights;
43pub use weights::*;
44
45#[frame_support::pallet]
46pub mod pallet {
47 use super::*;
48 use frame_support::pallet_prelude::*;
49 use frame_system::pallet_prelude::*;
50
51 /// The config trait of the pallet. You can basically do anything with the config trait that you
52 /// can do with a normal rust trait: import items consisting of types, constants and functions.
53 ///
54 /// A very common pattern is for a pallet to import implementations of traits such as
55 /// [`frame_support::traits::Currency`], [`frame_support::traits::fungibles::Inspect`] and
56 /// [`frame_support::traits::Get`]. These are all types that the pallet is delegating to the top
57 /// level runtime to provide to it.
58 ///
59 /// The `FRAME`-specific syntax are:
60 ///
61 /// * the use of `#[pallet::constant]`([`frame_support::procedural`]), which places a `Get`
62 /// implementation in the metadata.
63 /// * `type RuntimeEvent`, which is mandatory if your pallet has events. See TODO.
64 /// * Needless to say, because [`Config`] is bounded by [`frame_system::Config`], you can use
65 /// all the items from [`frame_system::Config`] as well, such as `AccountId`.
66 /// * `#[pallet::disable_frame_system_supertrait_check]` would remove the need for
67 /// `frame_system::Config` to exist, which you should almost never need.
68 #[pallet::config]
69 pub trait Config: frame_system::Config {
70 /// The overarching runtime event type.
71 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
72
73 /// Type representing the weight of this pallet
74 type WeightInfo: WeightInfo;
75
76 /// This is a normal Rust type, nothing specific to FRAME here.
77 type Currency: frame_support::traits::fungible::Inspect<Self::AccountId>;
78
79 /// Similarly, let the runtime decide this.
80 fn some_function() -> u32;
81
82 /// And this
83 const FOO: u32;
84
85 /// This is a FRAME-specific item. It will be placed in the metadata of the pallet, and
86 /// therefore can be queried by offchain applications.
87 #[pallet::constant]
88 type InMetadata: Get<u32>;
89 }
90
91 /// Allows you to define some extra constants to be added into constant metadata.
92 #[pallet::extra_constants]
93 impl<T: Config> Pallet<T> {
94 #[allow(non_snake_case)]
95 fn SomeValue() -> u32 {
96 unimplemented!()
97 }
98
99 #[pallet::constant_name(OtherValue)]
100 fn arbitrary_name() -> u32 {
101 unimplemented!()
102 }
103 }
104
105 const STORAGE_VERSION: frame_support::traits::StorageVersion = StorageVersion::new(1);
106
107 /// The pallet struct. There's nothing special to FRAME about this; it can implement functions
108 /// in an impl blocks, traits and so on.
109 #[pallet::pallet]
110 #[pallet::without_storage_info]
111 #[pallet::storage_version(STORAGE_VERSION)]
112 pub struct Pallet<T>(_);
113
114 /// Allows you to define some origin for the pallet.
115 #[pallet::origin]
116 pub type Origin<T> = frame_system::RawOrigin<<T as frame_system::Config>::AccountId>;
117
118 // first, we showcase all the possible storage types, with most of their details.
119
120 /// A storage value. We mark this as unbounded, alter its prefix, and define a custom storage
121 /// getter for it.
122 ///
123 /// The value is stored a single trie node, and therefore can be retrieved with a single
124 /// database access.
125 #[pallet::storage]
126 #[pallet::unbounded] // optional
127 #[pallet::storage_prefix = "OtherFoo"] // optional
128 #[pallet::getter(fn foo)] // optional
129 pub type Foo<T> = StorageValue<Value = u32>;
130
131 #[pallet::type_value]
132 pub fn DefaultForFoo() -> u32 {
133 1
134 }
135
136 #[pallet::storage]
137 pub type FooWithDefault<T> =
138 StorageValue<Value = u32, QueryKind = ValueQuery, OnEmpty = DefaultForFoo>;
139
140 /// A storage map. This creates a mapping from keys of type `u32` to values of type `u32`.
141 ///
142 /// Keys and values can be iterated, albeit each value is stored under a unique trie key,
143 /// meaning that an iteration consists of many database accesses.
144 #[pallet::storage]
145 pub type Bar<T> = StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
146
147 /// Conceptually same as `StorageMap<>` where the key is a tuple of `(u32, u32)`. On top, it
148 /// provides some functions to iterate or remove items based on only the first key.
149 #[pallet::storage]
150 pub type Qux<T> = StorageDoubleMap<
151 Hasher1 = Blake2_128Concat,
152 Key1 = u32,
153 Hasher2 = Blake2_128Concat,
154 Key2 = u32,
155 Value = u32,
156 >;
157
158 /// Same as `StorageDoubleMap`, but with arbitrary number of keys.
159 #[pallet::storage]
160 pub type Quux<T> = StorageNMap<
161 Key = (
162 NMapKey<Blake2_128Concat, u8>,
163 NMapKey<Blake2_128Concat, u16>,
164 NMapKey<Blake2_128Concat, u32>,
165 ),
166 Value = u64,
167 >;
168
169 /// In all of these examples, we chose a syntax where the storage item is defined using the
170 /// explicit generic syntax (`X = Y`). Alternatively:
171 #[pallet::storage]
172 pub type AlternativeSyntax<T> = StorageMap<_, Blake2_128Concat, u32, u32>;
173
174 /// Lastly, all storage items, as you saw, had to be generic over `T`. If they want to use an
175 /// item from `Config`, `<T: Config>` should be used.
176 #[pallet::storage]
177 pub type AlternativeSyntax2<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, u32>;
178
179 /// The genesis config type. This allows the pallet to define how it should initialized upon
180 /// genesis.
181 ///
182 /// It can be generic over `T` or not, depending on whether it is or not.
183 #[pallet::genesis_config]
184 pub struct GenesisConfig<T: Config> {
185 pub foo: u32,
186 pub bar: BlockNumberFor<T>,
187 }
188
189 impl<T: Config> Default for GenesisConfig<T> {
190 fn default() -> Self {
191 Self { foo: 0, bar: Default::default() }
192 }
193 }
194
195 /// Allows you to define how `genesis_configuration is built.
196 #[pallet::genesis_build]
197 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
198 fn build(&self) {
199 Foo::<T>::put(self.foo);
200 }
201 }
202
203 /// The call declaration. This states the entry points that we handle. The
204 /// macro takes care of the marshalling of arguments and dispatch.
205 #[pallet::call]
206 impl<T: Config> Pallet<T> {
207 #[pallet::call_index(0)]
208 #[pallet::weight(T::WeightInfo::set_foo_benchmark())]
209 /// Marks this call as feeless if `new_foo` is zero.
210 #[pallet::feeless_if(|_origin: &OriginFor<T>, new_foo: &u32, _other_compact: &u128| -> bool {
211 *new_foo == 0
212 })]
213 pub fn set_foo(
214 _: OriginFor<T>,
215 new_foo: u32,
216 #[pallet::compact] _other_compact: u128,
217 ) -> DispatchResult {
218 Foo::<T>::set(Some(new_foo));
219
220 Ok(())
221 }
222 }
223
224 /// The event type. This exactly like a normal Rust enum.
225 ///
226 /// It can or cannot be generic over `<T: Config>`. Note that unlike a normal enum, if none of
227 /// the variants actually use `<T: Config>`, the macro will generate a hidden `PhantomData`
228 /// variant.
229 ///
230 /// The `generate_deposit` macro generates a function on `Pallet` called `deposit_event` which
231 /// will properly convert the error type of your pallet into `RuntimeEvent` (recall `type
232 /// RuntimeEvent: From<Event<Self>>`, so it can be converted) and deposit it via
233 /// `frame_system::Pallet::deposit_event`.
234 #[pallet::event]
235 #[pallet::generate_deposit(pub fn deposit_event)]
236 pub enum Event<T: Config> {
237 /// A simple tuple style variant.
238 SomethingHappened(u32),
239 /// A simple struct-style variant. Note that we use `AccountId` from `T` because `T:
240 /// Config`, which by extension implies `T: frame_system::Config`.
241 SomethingDetailedHappened { at: u32, to: T::AccountId },
242 /// Another variant.
243 SomeoneJoined(T::AccountId),
244 }
245
246 /// The error enum. Must always be generic over `<T>`, which is expanded to `<T: Config>`.
247 #[pallet::error]
248 pub enum Error<T> {
249 SomethingWentWrong,
250 SomethingBroke,
251 }
252
253 /// All the possible hooks that a pallet can have. See [`frame_support::traits::Hooks`] for more
254 /// info.
255 #[pallet::hooks]
256 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
257 fn integrity_test() {}
258
259 fn offchain_worker(_n: BlockNumberFor<T>) {
260 unimplemented!()
261 }
262
263 fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
264 unimplemented!()
265 }
266
267 fn on_finalize(_n: BlockNumberFor<T>) {
268 unimplemented!()
269 }
270
271 fn on_idle(_n: BlockNumberFor<T>, _remaining_weight: Weight) -> Weight {
272 unimplemented!()
273 }
274
275 fn on_runtime_upgrade() -> Weight {
276 unimplemented!()
277 }
278
279 #[cfg(feature = "try-runtime")]
280 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
281 unimplemented!()
282 }
283
284 #[cfg(feature = "try-runtime")]
285 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
286 unimplemented!()
287 }
288
289 #[cfg(feature = "try-runtime")]
290 fn try_state(_n: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
291 unimplemented!()
292 }
293 }
294
295 /// Allows you to define an enum on the pallet which will then instruct `construct_runtime` to
296 /// amalgamate all similarly-named enums from other pallets into an aggregate enum.
297 #[pallet::composite_enum]
298 pub enum HoldReason {
299 Staking,
300 }
301
302 /// Allows the pallet to validate some unsigned transaction. See
303 /// [`sp_runtime::traits::ValidateUnsigned`] for more info.
304 #[pallet::validate_unsigned]
305 impl<T: Config> ValidateUnsigned for Pallet<T> {
306 type Call = Call<T>;
307 fn validate_unsigned(_: TransactionSource, _: &Self::Call) -> TransactionValidity {
308 unimplemented!()
309 }
310
311 fn pre_dispatch(_: &Self::Call) -> Result<(), TransactionValidityError> {
312 unimplemented!()
313 }
314 }
315
316 /// Allows the pallet to provide some inherent. See [`frame_support::inherent::ProvideInherent`]
317 /// for more info.
318 #[pallet::inherent]
319 impl<T: Config> ProvideInherent for Pallet<T> {
320 type Call = Call<T>;
321 type Error = MakeFatalError<()>;
322
323 const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234";
324
325 fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
326 unimplemented!();
327 }
328
329 fn is_inherent(_call: &Self::Call) -> bool {
330 unimplemented!()
331 }
332 }
333}