在runtime中聲明一個(gè)常量值是定義固定值或定義根據(jù)某些因素動(dòng)態(tài)變化的值的有用工具佳遂。
接下來一起看看乞而,如何創(chuàng)建用于重置u32存儲(chǔ)值的pallet常量。這個(gè)值量没,我們稱之為SingleValue
,也可以使用一個(gè)名為add_value
的方法來修改突想。
配置pallet的類型殴蹄、事件和錯(cuò)誤
1.定義pallet中的常量
-
MaxAddend
將是元數(shù)據(jù)中顯示的值。 -
ClearFrequency
跟蹤塊編號(hào)并將用于重置SingleValue
猾担。
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
#[pallet::constant] // put the constant in metadata
/// Maximum amount added per invocation.
type MaxAddend: Get<u32>;
/// Frequency with which the stored value is deleted.
type ClearFrequency: Get<Self::BlockNumber>;
}
2.聲明存儲(chǔ)項(xiàng)目和事件袭灯。
使用存儲(chǔ)屬性宏,聲明SingleValue
每個(gè)塊周期都會(huì)修改的值绑嘹。
#[pallet::storage]
#[pallet::getter(fn single_value)]
pub(super) type SingleValue<T: Config> = StorageValue<_, u32, ValueQuery>;
3.定義pallet的事件稽荧。
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// The value has been added to. The parameters are
/// (initial amount, amount added, final amount).
Added(u32, u32, u32),
/// The value has been cleared. The parameter is the value before clearing.
Cleared(u32)
}
4. 添加處理操作溢出的錯(cuò)誤:
#[pallet::error]
pub enum Error<T> {
/// An operation would lead to an overflow.
Overflow
}
創(chuàng)建pallet方法和運(yùn)行時(shí)常量
1.配置on_finalize.
在塊執(zhí)行結(jié)束時(shí)運(yùn)行的 on_finalize 函數(shù)中的每個(gè) ClearFrequency 塊數(shù)將 SingleValue 設(shè)置為 0。 在 #[pallet::hooks] 屬性下指定此邏輯
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_finalize(n: T::BlockNumber) {
if (n % T::ClearFrequency::get()).is_zero() {
let current_value = <SingleValue<T>>::get();
<SingleValue<T>>::put(0u32);
Self::deposit_event(Event::Cleared(current_value));
}
}
}
2.創(chuàng)建一個(gè)允許用戶指定值的方法工腋。
只要每次調(diào)用增加的值小于 MaxAddend 值姨丈,add_value 方法就會(huì)增加 SingleValue
畅卓。
對(duì)于此方法,必須遵循以下:
- Include checks.
- Keep track of the previous value.
- Check for overflow.
- Update SingleValue.
// Extrinsics callable from outside the runtime.
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000)]
fn add_value(
origin: OriginFor<T>,
val_to_add: u32
) -> DispatchResultWithPostInfo {
let _ = ensure_signed(origin)?;
ensure!(val_to_add <= T::MaxAddend::get(), "value must be <= maximum add amount constant");
// previous value got
let c_val = SingleValue::<T>::get();
// checks for overflow when new value added
let result = c_val.checked_add(val_to_add).ok_or(Error::<T>::Overflow)?;
<SingleValue<T>>::put(result);
Self::deposit_event(Event::Added(c_val, val_to_add, result));
Ok(().into())
}
}
3.為runtime提供常量值蟋恬。
在 runtime/src/lib.rs
中翁潘,為您的托盤的 MaxAddend
和 ClearFrequency
的運(yùn)行時(shí)實(shí)現(xiàn)聲明值:
parameter_types! {
pub const MaxAddend: u32 = 1738;
pub const ClearFrequency: u32 = 10;
}
impl constant_config::Config for Runtime {
type Event = Event;
type MaxAddend = MaxAddend;
type ClearFrequency = ClearFrequency;
}
例子
#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
use frame_system::pallet_prelude::*;
use frame_support::sp_runtime::traits::Zero;
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
#[pallet::constant] // put the constant in metadata
/// Maximum amount added per invocation.
type MaxAddend: Get<u32>;
/// Frequency with which the stored value is deleted.
type ClearFrequency: Get<Self::BlockNumber>;
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::storage]
#[pallet::getter(fn single_value)]
pub(super) type SingleValue<T: Config> = StorageValue<_, u32, ValueQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// The value has ben added to. The parameters are
/// (initial amount, amount added, final amount).
Added(u32, u32, u32),
/// The value has been cleared. The parameter is the value before clearing.
Cleared(u32)
}
#[pallet::error]
pub enum Error<T> {
/// An operation would lead to an overflow.
Overflow
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_finalize(n: T::BlockNumber) {
if (n % T::ClearFrequency::get()).is_zero() {
let current_value = <SingleValue<T>>::get();
<SingleValue<T>>::put(0u32);
Self::deposit_event(Event::Cleared(current_value));
}
}
}
// Extrinsics callable from outside the runtime.
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000)]
fn add_value(
origin: OriginFor<T>,
val_to_add: u32
) -> DispatchResultWithPostInfo {
let _ = ensure_signed(origin)?;
ensure!(val_to_add <= T::MaxAddend::get(), "value must be <= maximum add amount constant");
// previous value got
let c_val = SingleValue::<T>::get();
// checks for overflow when new value added
let result = c_val.checked_add(val_to_add).ok_or(Error::<T>::Overflow)?;
<SingleValue<T>>::put(result);
Self::deposit_event(Event::Added(c_val, val_to_add, result));
Ok(().into())
}
}
}