lib.rs 98.8 KiB
Newer Older
			#[crate::storage_alias]
			type GenericData2<T> = StorageMap<
				Blake2_128Concat,
				<T as Config>::BlockNumber,
				<T as Config>::BlockNumber,
			>;
			assert_eq!(Pallet::<Runtime>::generic_data2(5), None);
			GenericData2::<Runtime>::insert(5, 5);
			assert_eq!(Pallet::<Runtime>::generic_data2(5), Some(5));

			/// Some random docs that ensure that docs are accepted
			#[crate::storage_alias]
			pub type GenericData<T> = StorageMap<
				Test2,
				Blake2_128Concat,
				<T as Config>::BlockNumber,
				<T as Config>::BlockNumber,
			>;
	#[test]
	fn storage_value_mutate_exists_should_work() {
		new_test_ext().execute_with(|| {
			#[crate::storage_alias]
			pub type Value = StorageValue<Test, u32>;

			assert!(!Value::exists());

			Value::mutate_exists(|v| *v = Some(1));
			assert!(Value::exists());
			assert_eq!(Value::get(), Some(1));

			// removed if mutated to `None`
			Value::mutate_exists(|v| *v = None);
			assert!(!Value::exists());
		});
	}

	#[test]
	fn storage_value_try_mutate_exists_should_work() {
		new_test_ext().execute_with(|| {
			#[crate::storage_alias]
			pub type Value = StorageValue<Test, u32>;

			type TestResult = result::Result<(), &'static str>;

			assert!(!Value::exists());

			// mutated if `Ok`
			assert_ok!(Value::try_mutate_exists(|v| -> TestResult {
				*v = Some(1);
				Ok(())
			}));
			assert!(Value::exists());
			assert_eq!(Value::get(), Some(1));

			// no-op if `Err`
			assert_noop!(
				Value::try_mutate_exists(|v| -> TestResult {
					*v = Some(2);
					Err("nah")
				}),
				"nah"
			);
			assert_eq!(Value::get(), Some(1));

			// removed if mutated to`None`
			assert_ok!(Value::try_mutate_exists(|v| -> TestResult {
				*v = None;
				Ok(())
			}));
			assert!(!Value::exists());
		});
	}

	fn map_issue_3318() {
		new_test_ext().execute_with(|| {
			type OptionLinkedMap = self::frame_system::OptionLinkedMap<Runtime>;

			OptionLinkedMap::insert(1, 1);
			assert_eq!(OptionLinkedMap::get(1), Some(1));
			OptionLinkedMap::insert(1, 2);
			assert_eq!(OptionLinkedMap::get(1), Some(2));
		});
	}

thiolliere's avatar
thiolliere committed
	#[test]
	fn map_swap_works() {
		new_test_ext().execute_with(|| {
			type OptionLinkedMap = self::frame_system::OptionLinkedMap<Runtime>;

thiolliere's avatar
thiolliere committed
			OptionLinkedMap::insert(0, 0);
			OptionLinkedMap::insert(1, 1);
			OptionLinkedMap::insert(2, 2);
			OptionLinkedMap::insert(3, 3);

			let collect = || OptionLinkedMap::iter().collect::<Vec<_>>().sorted();
			assert_eq!(collect(), vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
thiolliere's avatar
thiolliere committed

			// Two existing
			OptionLinkedMap::swap(1, 2);
			assert_eq!(collect(), vec![(0, 0), (1, 2), (2, 1), (3, 3)]);
thiolliere's avatar
thiolliere committed

			// Back to normal
			OptionLinkedMap::swap(2, 1);
			assert_eq!(collect(), vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
thiolliere's avatar
thiolliere committed

			// Left existing
			OptionLinkedMap::swap(2, 5);
			assert_eq!(collect(), vec![(0, 0), (1, 1), (3, 3), (5, 2)]);
thiolliere's avatar
thiolliere committed

			// Right existing
			OptionLinkedMap::swap(5, 2);
			assert_eq!(collect(), vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
	#[test]
	fn double_map_swap_works() {
		new_test_ext().execute_with(|| {
			DataDM::insert(0, 1, 1);
			DataDM::insert(1, 0, 2);
			DataDM::insert(1, 1, 3);

			let get_all = || {
				vec![
					DataDM::get(0, 1),
					DataDM::get(1, 0),
					DataDM::get(1, 1),
					DataDM::get(2, 0),
					DataDM::get(2, 1),
				]
			};
			assert_eq!(get_all(), vec![1, 2, 3, 0, 0]);

			// Two existing
			DataDM::swap(0, 1, 1, 0);
			assert_eq!(get_all(), vec![2, 1, 3, 0, 0]);

			// Left existing
			DataDM::swap(1, 0, 2, 0);
			assert_eq!(get_all(), vec![2, 0, 3, 1, 0]);

			// Right existing
			DataDM::swap(2, 1, 1, 1);
			assert_eq!(get_all(), vec![2, 0, 0, 1, 3]);
		});
	}

	#[test]
	fn map_basic_insert_remove_should_work() {
		new_test_ext().execute_with(|| {
			// initialized during genesis
			assert_eq!(Map::get(&15u32), 42u64);

			// get / insert / take
			let key = 17u32;
			assert_eq!(Map::get(&key), 0u64);
			Map::insert(key, 4u64);
			assert_eq!(Map::get(&key), 4u64);
			assert_eq!(Map::take(&key), 4u64);
			assert_eq!(Map::get(&key), 0u64);

			// mutate
			Map::mutate(&key, |val| {
				*val = 15;
			});
			assert_eq!(Map::get(&key), 15u64);

			// remove
			Map::remove(&key);
			assert_eq!(Map::get(&key), 0u64);
		});
	}

	#[test]
	fn map_iteration_should_work() {
		new_test_ext().execute_with(|| {
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(15, 42)]);
			// insert / remove
			let key = 17u32;
			Map::insert(key, 4u64);
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(15, 42), (key, 4)]);
			assert_eq!(Map::take(&15), 42u64);
			assert_eq!(Map::take(&key), 4u64);
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![]);

			// Add couple of more elements
			Map::insert(key, 42u64);
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key, 42)]);
			Map::insert(key + 1, 43u64);
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key, 42), (key + 1, 43)]);

			// mutate
			let key = key + 2;
			Map::mutate(&key, |val| {
				*val = 15;
			});
			assert_eq!(
				Map::iter().collect::<Vec<_>>().sorted(),
				vec![(key - 2, 42), (key - 1, 43), (key, 15)]
			);
			Map::mutate(&key, |val| {
				*val = 17;
			});
			assert_eq!(
				Map::iter().collect::<Vec<_>>().sorted(),
				vec![(key - 2, 42), (key - 1, 43), (key, 17)]
			);

			// remove first
			Map::remove(&key);
			assert_eq!(
				Map::iter().collect::<Vec<_>>().sorted(),
				vec![(key - 2, 42), (key - 1, 43)]
			);

			// remove last from the list
			Map::remove(&(key - 2));
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 1, 43)]);

			// remove the last element
			Map::remove(&(key - 1));
			assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![]);
	#[test]
	fn double_map_basic_insert_remove_remove_prefix_with_commit_should_work() {
		let key1 = 17u32;
		let key2 = 18u32;
		type DoubleMap = self::frame_system::DataDM<Runtime>;
		let mut e = new_test_ext();
		e.execute_with(|| {
			// initialized during genesis
			assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64);

			// get / insert / take
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			DoubleMap::insert(&key1, &key2, &4u64);
			assert_eq!(DoubleMap::get(&key1, &key2), 4u64);
			assert_eq!(DoubleMap::take(&key1, &key2), 4u64);
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);

			// mutate
			DoubleMap::mutate(&key1, &key2, |val| *val = 15);
			assert_eq!(DoubleMap::get(&key1, &key2), 15u64);

			// remove
			DoubleMap::remove(&key1, &key2);
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);

			// remove prefix
			DoubleMap::insert(&key1, &key2, &4u64);
			DoubleMap::insert(&key1, &(key2 + 1), &4u64);
			DoubleMap::insert(&(key1 + 1), &key2, &4u64);
			DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64);
		});
		e.commit_all().unwrap();
		e.execute_with(|| {
			assert!(matches!(
				DoubleMap::clear_prefix(&key1, u32::max_value(), None),
				MultiRemovalResults { maybe_cursor: None, backend: 2, unique: 2, loops: 2 }
			));
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
			assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64);
			assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64);
		});
	}

	#[test]
	fn double_map_basic_insert_remove_remove_prefix_should_work() {
		new_test_ext().execute_with(|| {
			let key1 = 17u32;
			let key2 = 18u32;
			type DoubleMap = self::frame_system::DataDM<Runtime>;
			// initialized during genesis
			assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64);

			// get / insert / take
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			DoubleMap::insert(&key1, &key2, &4u64);
			assert_eq!(DoubleMap::get(&key1, &key2), 4u64);
			assert_eq!(DoubleMap::take(&key1, &key2), 4u64);
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			DoubleMap::mutate(&key1, &key2, |val| *val = 15);
			assert_eq!(DoubleMap::get(&key1, &key2), 15u64);
			DoubleMap::remove(&key1, &key2);
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			DoubleMap::insert(&key1, &key2, &4u64);
			DoubleMap::insert(&key1, &(key2 + 1), &4u64);
			DoubleMap::insert(&(key1 + 1), &key2, &4u64);
			DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64);
			// all in overlay
			assert!(matches!(
				DoubleMap::clear_prefix(&key1, u32::max_value(), None),
				MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 }
			));
			// Note this is the incorrect answer (for now), since we are using v2 of
			// `clear_prefix`.
			// When we switch to v3, then this will become:
			//   MultiRemovalResults:: { maybe_cursor: None, backend: 0, unique: 2, loops: 2 },
			assert!(matches!(
				DoubleMap::clear_prefix(&key1, u32::max_value(), None),
				MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 }
			assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
			assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
			assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64);
			assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64);
		});
	}

	#[test]
	fn double_map_append_should_work() {
		new_test_ext().execute_with(|| {
			type DoubleMap = self::frame_system::AppendableDM<Runtime>;

			let key1 = 17u32;
			let key2 = 18u32;

			DoubleMap::insert(&key1, &key2, &vec![1]);
			DoubleMap::append(&key1, &key2, 2);
			assert_eq!(DoubleMap::get(&key1, &key2), &[1, 2]);
	#[test]
	fn double_map_mutate_exists_should_work() {
		new_test_ext().execute_with(|| {
			type DoubleMap = self::frame_system::DataDM<Runtime>;

			let (key1, key2) = (11, 13);

			// mutated
			DoubleMap::mutate_exists(key1, key2, |v| *v = Some(1));
			assert_eq!(DoubleMap::get(&key1, key2), 1);

			// removed if mutated to `None`
			DoubleMap::mutate_exists(key1, key2, |v| *v = None);
			assert!(!DoubleMap::contains_key(&key1, key2));
		});
	}

	#[test]
	fn double_map_try_mutate_exists_should_work() {
		new_test_ext().execute_with(|| {
			type DoubleMap = self::frame_system::DataDM<Runtime>;
			type TestResult = Result<(), &'static str>;

			let (key1, key2) = (11, 13);

			// mutated if `Ok`
			assert_ok!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
				*v = Some(1);
				Ok(())
			}));
			assert_eq!(DoubleMap::get(&key1, key2), 1);

			// no-op if `Err`
			assert_noop!(
				DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
					*v = Some(2);
					Err("nah")
				}),
				"nah"
			);

			// removed if mutated to`None`
			assert_ok!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
				*v = None;
				Ok(())
			}));
			assert!(!DoubleMap::contains_key(&key1, key2));
		});
	fn expected_metadata() -> PalletStorageMetadataIR {
		PalletStorageMetadataIR {
					modifier: StorageEntryModifierIR::Default,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![StorageHasherIR::Twox64Concat],
						key: scale_info::meta_type::<u32>(),
						value: scale_info::meta_type::<u64>(),
					},
					default: vec![0, 0, 0, 0, 0, 0, 0, 0],
					docs: vec![],
					name: "OptionLinkedMap",
					modifier: StorageEntryModifierIR::Optional,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![StorageHasherIR::Blake2_128Concat],
						key: scale_info::meta_type::<u32>(),
						value: scale_info::meta_type::<u32>(),
					},
					default: vec![0],
					docs: vec![],
					name: "GenericData",
					modifier: StorageEntryModifierIR::Default,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![StorageHasherIR::Identity],
						key: scale_info::meta_type::<u32>(),
						value: scale_info::meta_type::<u32>(),
					},
					default: vec![0, 0, 0, 0],
					docs: vec![],
					name: "GenericData2",
					modifier: StorageEntryModifierIR::Optional,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![StorageHasherIR::Blake2_128Concat],
						key: scale_info::meta_type::<u32>(),
						value: scale_info::meta_type::<u32>(),
					},
					default: vec![0],
					docs: vec![],
					modifier: StorageEntryModifierIR::Default,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![
							StorageHasherIR::Twox64Concat,
							StorageHasherIR::Blake2_128Concat,
						],
						key: scale_info::meta_type::<(u32, u32)>(),
						value: scale_info::meta_type::<u64>(),
					},
					default: vec![0, 0, 0, 0, 0, 0, 0, 0],
					docs: vec![],
					name: "GenericDataDM",
					modifier: StorageEntryModifierIR::Default,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![StorageHasherIR::Blake2_128Concat, StorageHasherIR::Identity],
						key: scale_info::meta_type::<(u32, u32)>(),
						value: scale_info::meta_type::<u32>(),
					},
					default: vec![0, 0, 0, 0],
					docs: vec![],
					name: "GenericData2DM",
					modifier: StorageEntryModifierIR::Optional,
					ty: StorageEntryTypeIR::Map {
						hashers: vec![
							StorageHasherIR::Blake2_128Concat,
							StorageHasherIR::Twox64Concat,
						],
						key: scale_info::meta_type::<(u32, u32)>(),
						value: scale_info::meta_type::<u32>(),
					},
					default: vec![0],
					docs: vec![],
					name: "AppendableDM",
					modifier: StorageEntryModifierIR::Default,
					ty: StorageEntryTypeIR::Map {
							StorageHasherIR::Blake2_128Concat,
							StorageHasherIR::Blake2_128Concat,
						],
						key: scale_info::meta_type::<(u32, u32)>(),
						value: scale_info::meta_type::<Vec<u32>>(),
					},
					default: vec![0],
					docs: vec![],

	#[test]
	fn store_metadata() {
		let metadata = Pallet::<Runtime>::storage_metadata();
		pretty_assertions::assert_eq!(expected_metadata(), metadata);

	parameter_types! {
		storage StorageParameter: u64 = 10;
	}

	#[test]
	fn check_storage_parameter_type_works() {
		TestExternalities::default().execute_with(|| {
			assert_eq!(sp_io::hashing::twox_128(b":StorageParameter:"), StorageParameter::key());

			assert_eq!(10, StorageParameter::get());

			StorageParameter::set(&300);
			assert_eq!(300, StorageParameter::get());
		})
	}
/// Private module re-exporting items used by frame support macros.
#[doc(hidden)]
pub mod _private {
	pub use sp_inherents;
}

/// Prelude to be used for pallet testing, for ease of use.
#[cfg(feature = "std")]
pub mod testing_prelude {
	pub use super::{
		assert_err, assert_err_ignore_postinfo, assert_err_with_weight, assert_error_encoded_size,
		assert_noop, assert_ok, assert_storage_noop, bounded_btree_map, bounded_vec,
		parameter_types, traits::Get,
	};
	pub use sp_arithmetic::assert_eq_error_rate;
}

/// Prelude to be used alongside pallet macro, for ease of use.
pub mod pallet_prelude {
	pub use crate::{
		dispatch::{
			DispatchClass, DispatchError, DispatchResult, DispatchResultWithPostInfo, Parameter,
			Pays,
		},
		ensure,
		inherent::{InherentData, InherentIdentifier, ProvideInherent},
		storage,
		storage::{
			bounded_vec::BoundedVec,
			types::{
				CountedStorageMap, Key as NMapKey, OptionQuery, ResultQuery, StorageDoubleMap,
				StorageMap, StorageNMap, StorageValue, ValueQuery,
			ConstU32, EnsureOrigin, GenesisBuild, Get, GetDefault, GetStorageVersion, Hooks,
			IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, TypedGet,
		Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity,
		PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat,
	pub use codec::{Decode, Encode, MaxEncodedLen};
	pub use frame_support::pallet_macros::*;
	pub use frame_support_procedural::register_default_impl;
	pub use scale_info::TypeInfo;
	pub use sp_inherents::MakeFatalError;
	pub use sp_runtime::{
		traits::{MaybeSerializeDeserialize, Member, ValidateUnsigned},
		transaction_validity::{
			InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource,
			TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction,
			ValidTransaction,
		MAX_MODULE_ERROR_ENCODED_SIZE,
	pub use sp_std::marker::PhantomData;
	pub use sp_weights::Weight;
/// The `pallet` attribute macro defines a pallet that can be used with
/// [`construct_runtime!`]. It must be attached to a module named `pallet` as follows:
///
/// ```ignore
/// #[pallet]
/// pub mod pallet {
/// Note that various types can be automatically imported using
/// [`frame_support::pallet_prelude`] and `frame_system::pallet_prelude`:
///
/// ```ignore
/// #[pallet]
/// pub mod pallet {
/// 	use frame_support::pallet_prelude::*;
/// 	use frame_system::pallet_prelude::*;
/// 	...
/// # pallet::* Attributes
///
/// The `pallet` macro will parse any items within your `pallet` module that are annotated with
/// `#[pallet::*]` attributes. Some of these attributes are mandatory and some are optional,
/// and they can attach to different types of items within your pallet depending on the
/// attribute in question. The full list of `#[pallet::*]` attributes is shown below in the
/// order in which they are mentioned in this document:
///
/// * [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory)
/// * [`pallet::config`](#config-trait-palletconfig-mandatory)
/// * [`pallet::constant`](#palletconstant)
/// * [`pallet::disable_frame_system_supertrait_check`](#disable_supertrait_check)
/// * [`pallet::generate_store($vis trait Store)`](#palletgenerate_storevis-trait-store)
/// * [`pallet::storage_version`](#palletstorage_version)
/// * [`pallet::hooks`](#hooks-pallethooks-optional)
/// * [`pallet::call`](#call-palletcall-optional)
/// * [`pallet::weight($expr)`](#palletweightexpr)
/// * [`pallet::compact`](#palletcompact-some_arg-some_type)
/// * [`pallet::call_index($idx)`](#palletcall_indexidx)
/// * [`pallet::extra_constants`](#extra-constants-palletextra_constants-optional)
/// * [`pallet::error`](#error-palleterror-optional)
/// * [`pallet::event`](#event-palletevent-optional)
/// * [`pallet::generate_deposit($visibility fn
///   deposit_event)`](#palletgenerate_depositvisibility-fn-deposit_event)
/// * [`pallet::storage`](#storage-palletstorage-optional)
/// * [`pallet::getter(fn $my_getter_fn_name)`](#palletgetterfn-my_getter_fn_name-optional)
/// * [`pallet::storage_prefix = "SomeName"`](#palletstorage_prefix--somename-optional)
/// * [`pallet::unbounded`](#palletunbounded-optional)
/// * [`pallet::whitelist_storage`](#palletwhitelist_storage-optional)
/// * [`cfg(..)`](#cfg-for-storage) (on storage items)
/// * [`pallet::type_value`](#type-value-pallettype_value-optional)
/// * [`pallet::genesis_config`](#genesis-config-palletgenesis_config-optional)
/// * [`pallet::genesis_build`](#genesis-build-palletgenesis_build-optional)
/// * [`pallet::inherent`](#inherent-palletinherent-optional)
/// * [`pallet::validate_unsigned`](#validate-unsigned-palletvalidate_unsigned-optional)
/// * [`pallet::origin`](#origin-palletorigin-optional)
/// * [`pallet::composite_enum`](#composite-enum-palletcomposite_enum-optional)
///
/// Note that at compile-time, the `#[pallet]` macro will analyze and expand all of these
/// attributes, ultimately removing their AST nodes before they can be parsed as real
/// attribute macro calls. This means that technically we do not need attribute macro
/// definitions for any of these attributes, however, for consistency and discoverability
/// reasons, we still maintain stub attribute macro definitions for all of these attributes in
/// the [`pallet_macros`] module which is automatically included in all pallets as part of the
/// pallet prelude. The actual "work" for all of these attribute macros can be found in the
/// macro expansion for `#[pallet]`.
///
/// Also note that in this document, pallet attributes are explained using the syntax of
/// non-instantiable pallets. For an example of an instantiable pallet, see [this
/// example](#example-of-an-instantiable-pallet).
///
/// # Dev Mode (`#[pallet(dev_mode)]`)
///
/// Specifying the argument `dev_mode` on the `#[pallet]` or `#[frame_support::pallet]`
/// attribute attached to your pallet module will allow you to enable dev mode for a pallet.
/// The aim of dev mode is to loosen some of the restrictions and requirements placed on
/// production pallets for easy tinkering and development. Dev mode pallets should not be used
/// in production. Enabling dev mode has the following effects:
///
/// * Weights no longer need to be specified on every `#[pallet::call]` declaration. By
///   default, dev mode pallets will assume a weight of zero (`0`) if a weight is not
///   specified. This is equivalent to specifying `#[weight(0)]` on all calls that do not
///   specify a weight.
/// * All storages are marked as unbounded, meaning you do not need to implement
///   `MaxEncodedLen` on storage types. This is equivalent to specifying `#[pallet::unbounded]`
///   on all storage type definitions.
///
/// Note that the `dev_mode` argument can only be supplied to the `#[pallet]` or
/// `#[frame_support::pallet]` attribute macro that encloses your pallet module. This argument
/// cannot be specified anywhere else, including but not limited to the `#[pallet::pallet]`
/// attribute macro.
///
/// <div class="example-wrap" style="display:inline-block"><pre class="compile_fail"
/// style="white-space:normal;font:inherit;">
/// <strong>WARNING</strong>:
/// You should not deploy or use dev mode pallets in production. Doing so can break your chain
/// and therefore should never be done. Once you are done tinkering, you should remove the
/// 'dev_mode' argument from your #[pallet] declaration and fix any compile errors before
/// attempting to use your pallet in a production scenario.
/// </pre></div>
///
/// # Pallet struct placeholder: `#[pallet::pallet]` (mandatory)
///
/// The pallet struct placeholder `#[pallet::pallet]` is mandatory and allows you to specify
/// pallet information.
///
/// The struct must be defined as follows:
/// ```ignore
/// #[pallet::pallet]
/// pub struct Pallet<T>(_);
/// ```
/// I.e. a regular struct definition named `Pallet`, with generic T and no where clause.
/// ## Macro expansion:
///
/// The macro adds this attribute to the struct definition:
/// ```ignore
/// #[derive(
/// 	frame_support::CloneNoBound,
/// 	frame_support::EqNoBound,
/// 	frame_support::PartialEqNoBound,
/// 	frame_support::RuntimeDebugNoBound,
/// )]
/// ```
/// and replaces the type `_` with `PhantomData<T>`. It also implements on the pallet:
/// * [`GetStorageVersion`](`traits::GetStorageVersion`)
/// * [`OnGenesis`](`traits::OnGenesis`): contains some logic to write the pallet version into
///   storage.
/// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined.
///
/// It declares `type Module` type alias for `Pallet`, used by `construct_runtime`.
///
/// It implements [`PalletInfoAccess`](`traits::PalletInfoAccess') on `Pallet` to ease access
/// to pallet information given by [`frame_support::traits::PalletInfo`]. (The implementation
/// uses the associated type `frame_system::Config::PalletInfo`).
///
/// It implements [`StorageInfoTrait`](`traits::StorageInfoTrait`) on `Pallet` which give
/// information about all storages.
///
/// If the attribute `generate_store` is set then the macro creates the trait `Store` and
/// implements it on `Pallet`.
///
/// If the attribute `set_storage_max_encoded_len` is set then the macro calls
/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for each storage in the implementation of
/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for the pallet. Otherwise it implements
/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for the pallet using the
/// [`PartialStorageInfoTrait`](`traits::PartialStorageInfoTrait`) implementation of storages.
///
/// # Config trait: `#[pallet::config]` (mandatory)
///
/// The mandatory attribute `#[pallet::config]` defines the configurable options for the
/// pallet.
///
/// Item must be defined as:
///
/// ```ignore
/// #[pallet::config]
/// pub trait Config: frame_system::Config + $optionally_some_other_supertraits
/// $optional_where_clause
/// {
/// ...
/// }
/// ```
///
/// I.e. a regular trait definition named `Config`, with the supertrait
/// `frame_system::pallet::Config`, and optionally other supertraits and a where clause.
/// (Specifying other supertraits here is known as [tight
/// coupling](https://docs.substrate.io/reference/how-to-guides/pallet-design/use-tight-coupling/))
///
/// The associated type `RuntimeEvent` is reserved. If defined, it must have the bounds
/// `From<Event>` and `IsType<<Self as frame_system::Config>::RuntimeEvent>`.
///
/// [`pallet::event`](`frame_support::pallet_macros::event`) must be present if `RuntimeEvent`
/// exists as a config item in your `#[pallet::config]`.
///
/// Also see [`pallet::config`](`frame_support::pallet_macros::config`)
///
/// ## `pallet::constant`
///
/// The `#[pallet::constant]` attribute can be used to add an associated type trait bounded by
/// [`Get`](crate::traits::Get) from [`pallet::config`](#palletconfig) into metadata, e.g.:
///
/// ```ignore
/// #[pallet::config]
/// pub trait Config: frame_system::Config {
/// 	#[pallet::constant]
/// 	type Foo: Get<u32>;
/// Also see [`pallet::constant`](`frame_support::pallet_macros::constant`)
///
/// ## `pallet::disable_frame_system_supertrait_check`
/// <a name="disable_supertrait_check"></a>
///
/// To bypass the `frame_system::Config` supertrait check, use the attribute
/// `pallet::disable_frame_system_supertrait_check`, e.g.:
///
/// ```ignore
/// #[pallet::config]
/// #[pallet::disable_frame_system_supertrait_check]
/// pub trait Config: pallet_timestamp::Config {}
/// ```
///
/// NOTE: Bypassing the `frame_system::Config` supertrait check is typically desirable when you
/// want to write an alternative to the `frame_system` pallet.
/// Also see
/// [`pallet::disable_frame_system_supertrait_check`](`frame_support::pallet_macros::disable_frame_system_supertrait_check`)
/// The macro expands pallet constant metadata with the information given by
/// `#[pallet::constant]`.
/// # `pallet::generate_store($vis trait Store)`
///
/// To generate a `Store` trait associating all storages, annotate your `Pallet` struct with
/// the attribute `#[pallet::generate_store($vis trait Store)]`, e.g.:
///
/// ```ignore
/// #[pallet::pallet]
/// #[pallet::generate_store(pub(super) trait Store)]
/// More precisely, the `Store` trait contains an associated type for each storage. It is
/// implemented for `Pallet` allowing access to the storage from pallet struct.
///
/// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using
/// `<Pallet as Store>::Foo`.
///
/// NOTE: this attribute is only valid when applied _directly_ to your `Pallet` struct
/// definition.
///
/// Also see [`pallet::generate_store`](`frame_support::pallet_macros::generate_store`).
///
/// # `pallet::storage_version`
///
/// Because the [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory) macro
/// implements [`traits::GetStorageVersion`], the current storage version needs to be
/// communicated to the macro. This can be done by using the `pallet::storage_version`
/// attribute:
///
/// ```ignore
/// const STORAGE_VERSION: StorageVersion = StorageVersion::new(5);
///
/// #[pallet::pallet]
/// #[pallet::storage_version(STORAGE_VERSION)]
/// pub struct Pallet<T>(_);
/// ```
///
/// If not present, the current storage version is set to the default value.
///
/// Also see [`pallet::storage_version`](`frame_support::pallet_macros::storage_version`)
/// # Hooks: `#[pallet::hooks]` (optional)
/// The `pallet::hooks` attribute allows you to specify a `Hooks` implementation for `Pallet`
/// that specifies pallet-specific logic.
/// The item the attribute attaches to must be defined as follows:
/// ```ignore
/// #[pallet::hooks]
/// impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> $optional_where_clause {
/// }
/// ```
/// I.e. a regular trait implementation with generic bound: `T: Config`, for the trait
/// `Hooks<BlockNumberFor<T>>` (they are defined in preludes), for the type `Pallet<T>` and
/// with an optional where clause.
/// If no `#[pallet::hooks]` exists, then the following default implementation is
/// automatically generated:
/// ```ignore
/// #[pallet::hooks]
/// impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
/// ```
///
/// Also see [`pallet::hooks`](`frame_support::pallet_macros::hooks`)
/// # Call: `#[pallet::call]` (optional)
///
/// Implementation of pallet dispatchables.
///
/// Item must be defined as:
/// ```ignore
/// #[pallet::call]
/// impl<T: Config> Pallet<T> {
/// 	/// $some_doc
/// 	#[pallet::weight($ExpressionResultingInWeight)]
/// 	pub fn $fn_name(
/// 		origin: OriginFor<T>,
/// 		$some_arg: $some_type,
/// 		// or with compact attribute: #[pallet::compact] $some_arg: $some_type,
/// 		...
/// 	) -> DispatchResultWithPostInfo { // or `-> DispatchResult`
/// 		...
/// 	}
/// 	...
/// }
/// ```
/// I.e. a regular type implementation, with generic `T: Config`, on type `Pallet<T>`, with
/// an optional where clause.
///
/// ## `#[pallet::weight($expr)]`
///
/// Each dispatchable needs to define a weight with `#[pallet::weight($expr)]` attribute, the
/// first argument must be `origin: OriginFor<T>`.
///
/// Also see [`pallet::weight`](`frame_support::pallet_macros::weight`)
///
/// ### `#[pallet::compact] $some_arg: $some_type`
///
/// Compact encoding for arguments can be achieved via `#[pallet::compact]`. The function must
/// return a `DispatchResultWithPostInfo` or `DispatchResult`.
/// Also see [`pallet::compact`](`frame_support::pallet_macros::compact`)
///
/// ## `#[pallet::call_index($idx)]`
/// Each dispatchable may also be annotated with the `#[pallet::call_index($idx)]` attribute,
/// which explicitly defines the codec index for the dispatchable function in the `Call` enum.
///
/// All call indexes start from 0, until it encounters a dispatchable function with a defined
/// call index. The dispatchable function that lexically follows the function with a defined
/// call index will have that call index, but incremented by 1, e.g. if there are 3
/// dispatchable functions `fn foo`, `fn bar` and `fn qux` in that order, and only `fn bar`
/// has a call index of 10, then `fn qux` will have an index of 11, instead of 1.
/// **WARNING**: modifying dispatchables, changing their order, removing some, etc., must be
/// done with care. Indeed this will change the outer runtime call type (which is an enum with
/// one variant per pallet), this outer runtime call can be stored on-chain (e.g. in
/// `pallet-scheduler`). Thus migration might be needed. To mitigate against some of this, the
/// `#[pallet::call_index($idx)]` attribute can be used to fix the order of the dispatchable so
/// that the `Call` enum encoding does not change after modification. As a general rule of
/// thumb, it is therefore adventageous to always add new calls to the end so you can maintain
/// the existing order of calls.
/// Also see [`pallet::call_index`](`frame_support::pallet_macros::call_index`)
/// # Extra constants: `#[pallet::extra_constants]` (optional)
/// Allows you to define some extra constants to be added into constant metadata.
///
/// Item must be defined as:
/// ```ignore
/// #[pallet::extra_constants]
/// impl<T: Config> Pallet<T> where $optional_where_clause {
/// 	/// $some_doc
/// 	$vis fn $fn_name() -> $some_return_type {
/// 		...
/// 	}
/// 	...
/// }
/// ```
/// I.e. a regular rust `impl` block with some optional where clause and functions with 0 args,
/// 0 generics, and some return type.
/// The macro add some extra constants to pallet constant metadata.
/// Also see: [`pallet::extra_constants`](`frame_support::pallet_macros::extra_constants`)
/// # Error: `#[pallet::error]` (optional)
///
/// The `#[pallet::error]` attribute allows you to define an error enum that will be returned
/// from the dispatchable when an error occurs. The information for this error type is then
/// stored in metadata.
///
/// Item must be defined as:
/// ```ignore
/// #[pallet::error]
/// pub enum Error<T> {
/// 	/// $some_optional_doc
/// 	$SomeFieldLessVariant,
/// 	/// $some_more_optional_doc
/// 	$SomeVariantWithOneField(FieldType),
/// I.e. a regular enum named `Error`, with generic `T` and fieldless or multiple-field
/// variants.
///
/// Any field type in the enum variants must implement [`scale_info::TypeInfo`] in order to be
/// properly used in the metadata, and its encoded size should be as small as possible,
/// preferably 1 byte in size in order to reduce storage size. The error enum itself has an
/// absolute maximum encoded size specified by [`MAX_MODULE_ERROR_ENCODED_SIZE`].
///
/// (1 byte can still be 256 different errors. The more specific the error, the easier it is to
/// diagnose problems and give a better experience to the user. Don't skimp on having lots of
/// individual error conditions.)
///
/// Field types in enum variants must also implement [`PalletError`](traits::PalletError),
/// otherwise the pallet will fail to compile. Rust primitive types have already implemented
/// the [`PalletError`](traits::PalletError) trait along with some commonly used stdlib types
/// such as [`Option`] and [`PhantomData`](`frame_support::dispatch::marker::PhantomData`), and
/// hence in most use cases, a manual implementation is not necessary and is discouraged.
/// The generic `T` must not bound anything and a `where` clause is not allowed. That said,
/// bounds and/or a where clause should not needed for any use-case.
/// Also see: [`pallet::error`](`frame_support::pallet_macros::error`)
/// # Event: `#[pallet::event]` (optional)
/// Allows you to define pallet events. Pallet events are stored under the `system` / `events`
/// key when the block is applied (and then replaced when the next block writes it's events).
/// The Event enum must be defined as follows:
///
/// ```ignore
/// #[pallet::event]
/// #[pallet::generate_deposit($visibility fn deposit_event)] // Optional