Attribute Macro frame_support::storage_alias

source ·
#[storage_alias]
Expand description

Generate a #[pallet::storage] alias outside of a pallet.

This storage alias works similarly to the #[pallet::storage] attribute macro. It supports StorageValue, StorageMap, StorageDoubleMap and StorageNMap. The main difference to the normal #[pallet::storage] is the flexibility around declaring the storage prefix to use. The storage prefix determines where to find the value in the storage. #[pallet::storage] uses the name of the pallet as declared in construct_runtime!.

The flexibility around declaring the storage prefix makes this macro very useful for writing migrations etc.

Examples

There are different ways to declare the prefix to use. The prefix type can either be declared explicetly by passing it to the macro as an attribute or by letting the macro guess on what the prefix type is. The prefix is always passed as the first generic argument to the type declaration. When using #[pallet::storage] this first generic argument is always _. Besides declaring the prefix, the rest of the type declaration works as with #[pallet::storage].

  1. Use the verbatim prefix type. This prefix type uses the given identifier as the prefix:
#[test]
fn verbatim_attribute() {
	new_test_ext().execute_with(|| {
		// Declare the alias that will use the verbatim identifier as prefix.
		#[crate::storage_alias(verbatim)]
		pub type Value = StorageValue<Test, u32>;

		// Check that it works as expected.
		Value::put(1);
		assert_eq!(1, Value::get().unwrap());

		// The prefix is the one we declared above.
		assert_eq!(&b"Test"[..], Value::module_prefix());
	});
}
  1. Use the pallet_name prefix type. This prefix type uses the name of the pallet as configured in construct_runtime! as the prefix:
#[test]
fn pallet_name_attribute() {
	new_test_ext().execute_with(|| {
		// Declare the alias that will use the pallet name as prefix.
		#[crate::storage_alias(pallet_name)]
		pub type Value<T: Config> = StorageValue<Pallet<T>, u32>;

		// Check that it works as expected.
		Value::<Runtime>::put(1);
		assert_eq!(1, Value::<Runtime>::get().unwrap());

		// The prefix is the pallet name. In this case the pallet name is `System` as declared in
		// `construct_runtime!`.
		assert_eq!(&b"System"[..], Value::<Runtime>::module_prefix());
	});
}

It requires that the given prefix type implements PalletInfoAccess (which is always the case for FRAME pallet structs). In the example above, Pallet<T> is the prefix type.

  1. Use the dynamic prefix type. This prefix type calls Get::get() to get the prefix:
#[test]
fn dynamic_attribute() {
	new_test_ext().execute_with(|| {
		// First let's declare our prefix.
		//
		// It could be any type that, as long as it implements `Get<&'static str>`.
		parameter_types! {
			pub Prefix: &'static str = "Hello";
		}

		// Declare the alias that will use the dynamic `Get` as prefix.
		#[crate::storage_alias(dynamic)]
		pub type Value<T: Get<&'static str>> = StorageValue<T, u32>;

		// Check that it works as expected.
		Value::<Prefix>::put(1);
		assert_eq!(1, Value::<Prefix>::get().unwrap());

		// The prefix is the one we declared above.
		assert_eq!(&b"Hello"[..], Value::<Prefix>::module_prefix());
	});
}

It requires that the given prefix type implements Get<'static str>.

  1. Let the macro “guess” what kind of prefix type to use. This only supports verbatim or pallet name. The macro uses the presence of generic arguments to the prefix type as an indication that it should use the pallet name as the prefix:
#[test]
fn storage_alias_guess() {
	new_test_ext().execute_with(|| {
		// The macro will use `Test` as prefix.
		#[crate::storage_alias]
		pub type Value = StorageValue<Test, u32>;

		assert_eq!(&b"Test"[..], Value::module_prefix());

		// The macro will use the pallet name as prefix.
		#[crate::storage_alias]
		pub type PalletValue<T: Config> = StorageValue<Pallet<T>, u32>;

		assert_eq!(&b"System"[..], PalletValue::<Runtime>::module_prefix());
	});
}