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]
.
- Use the
verbatim
prefix type. This prefix type uses the given identifier as theprefix
:
#[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());
});
}
- Use the
pallet_name
prefix type. This prefix type uses the name of the pallet as configured inconstruct_runtime!
as theprefix
:
#[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.
- Use the
dynamic
prefix type. This prefix type callsGet::get()
to get theprefix
:
#[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>
.
- 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());
});
}