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