referrerpolicy=no-referrer-when-downgrade

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}