Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Migrate pallet-nicks to pallet attribute macro. #8723

Merged
3 commits merged into from
May 5, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 79 additions & 71 deletions frame/nicks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Nicks Module
//! # Nicks Pallet
//!
//! - [`Config`]
//! - [`Call`]
//!
//! ## Overview
//!
//! Nicks is an example module for keeping track of account names on-chain. It makes no effort to
//! Nicks is an example pallet for keeping track of account names on-chain. It makes no effort to
//! create a name hierarchy, be a DNS replacement or provide reverse lookups. Furthermore, the
//! weights attached to this module's dispatchable functions are for demonstration purposes only and
//! weights attached to this pallet's dispatchable functions are for demonstration purposes only and
//! have not been designed to be economically secure. Do not use this pallet as-is in production.
//!
//! ## Interface
Expand All @@ -45,88 +45,85 @@ use sp_std::prelude::*;
use sp_runtime::{
traits::{StaticLookup, Zero}
};
use frame_support::{
decl_module, decl_event, decl_storage, ensure, decl_error,
traits::{Currency, EnsureOrigin, ReservableCurrency, OnUnbalanced, Get},
};
use frame_system::ensure_signed;
use frame_support::traits::{Currency, ReservableCurrency, OnUnbalanced};
pub use pallet::*;

type BalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;

pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
#[frame_support::pallet]
pub mod pallet {
use frame_system::{ensure_signed, pallet_prelude::*};
use frame_support::{ensure, pallet_prelude::*, traits::{EnsureOrigin, Get}};
use super::*;

/// The currency trait.
type Currency: ReservableCurrency<Self::AccountId>;
#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

/// Reservation fee.
type ReservationFee: Get<BalanceOf<Self>>;
/// The currency trait.
type Currency: ReservableCurrency<Self::AccountId>;

/// What to do with slashed funds.
type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;
/// Reservation fee.
#[pallet::constant]
type ReservationFee: Get<BalanceOf<Self>>;

/// The origin which may forcibly set or remove a name. Root can always do this.
type ForceOrigin: EnsureOrigin<Self::Origin>;
/// What to do with slashed funds.
type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;

/// The minimum length a name may be.
type MinLength: Get<usize>;
/// The origin which may forcibly set or remove a name. Root can always do this.
type ForceOrigin: EnsureOrigin<Self::Origin>;

/// The maximum length a name may be.
type MaxLength: Get<usize>;
}
/// The minimum length a name may be.
#[pallet::constant]
type MinLength: Get<u32>;
Copy link
Contributor Author

@shaunxw shaunxw May 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it should be fine to change it to Get<u32> here? The type in metadata is Get<u32>. Cannot find a better way to keep metadata type as Get<u32> type without changing the type in Config. #[pallet::extra_constant] seems for this scenario but the constant name will change, as functions in it should be named as snake case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is better now to me too


decl_storage! {
trait Store for Module<T: Config> as Nicks {
/// The lookup table for names.
NameOf: map hasher(twox_64_concat) T::AccountId => Option<(Vec<u8>, BalanceOf<T>)>;
/// The maximum length a name may be.
#[pallet::constant]
type MaxLength: Get<u32>;
}
}

decl_event!(
pub enum Event<T> where AccountId = <T as frame_system::Config>::AccountId, Balance = BalanceOf<T> {
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
#[pallet::metadata(T::AccountId = "AccountId", BalanceOf<T> = "Balance")]
pub enum Event<T: Config> {
/// A name was set. \[who\]
NameSet(AccountId),
NameSet(T::AccountId),
/// A name was forcibly set. \[target\]
NameForced(AccountId),
NameForced(T::AccountId),
/// A name was changed. \[who\]
NameChanged(AccountId),
NameChanged(T::AccountId),
/// A name was cleared, and the given balance returned. \[who, deposit\]
NameCleared(AccountId, Balance),
NameCleared(T::AccountId, BalanceOf<T>),
/// A name was removed and the given balance slashed. \[target, deposit\]
NameKilled(AccountId, Balance),
NameKilled(T::AccountId, BalanceOf<T>),
}
);

decl_error! {
/// Error for the nicks module.
pub enum Error for Module<T: Config> {
/// Error for the nicks pallet.
#[pallet::error]
pub enum Error<T> {
/// A name is too short.
TooShort,
/// A name is too long.
TooLong,
/// An account isn't named.
Unnamed,
}
}

decl_module! {
/// Nicks module declaration.
pub struct Module<T: Config> for enum Call where origin: T::Origin {
type Error = Error<T>;

fn deposit_event() = default;

/// Reservation fee.
const ReservationFee: BalanceOf<T> = T::ReservationFee::get();
/// The lookup table for names.
#[pallet::storage]
pub(super) type NameOf<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, (Vec<u8>, BalanceOf<T>)>;

/// The minimum length a name may be.
const MinLength: u32 = T::MinLength::get() as u32;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

/// The maximum length a name may be.
const MaxLength: u32 = T::MaxLength::get() as u32;
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Set an account's name. The name should be a UTF-8-encoded string by convention, though
/// we don't check it.
///
Expand All @@ -143,24 +140,25 @@ decl_module! {
/// - One storage read/write.
/// - One event.
/// # </weight>
#[weight = 50_000_000]
fn set_name(origin, name: Vec<u8>) {
#[pallet::weight(50_000_000)]
pub(super) fn set_name(origin: OriginFor<T>, name: Vec<u8>) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;

ensure!(name.len() >= T::MinLength::get(), Error::<T>::TooShort);
ensure!(name.len() <= T::MaxLength::get(), Error::<T>::TooLong);
ensure!(name.len() >= T::MinLength::get() as usize, Error::<T>::TooShort);
ensure!(name.len() <= T::MaxLength::get() as usize, Error::<T>::TooLong);

let deposit = if let Some((_, deposit)) = <NameOf<T>>::get(&sender) {
Self::deposit_event(RawEvent::NameChanged(sender.clone()));
Self::deposit_event(Event::<T>::NameChanged(sender.clone()));
deposit
} else {
let deposit = T::ReservationFee::get();
T::Currency::reserve(&sender, deposit.clone())?;
Self::deposit_event(RawEvent::NameSet(sender.clone()));
Self::deposit_event(Event::<T>::NameSet(sender.clone()));
deposit
};

<NameOf<T>>::insert(&sender, (name, deposit));
Ok(().into())
}

/// Clear an account's name and return the deposit. Fails if the account was not named.
Expand All @@ -173,16 +171,17 @@ decl_module! {
/// - One storage read/write.
/// - One event.
/// # </weight>
#[weight = 70_000_000]
fn clear_name(origin) {
#[pallet::weight(70_000_000)]
pub(super) fn clear_name(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;

let deposit = <NameOf<T>>::take(&sender).ok_or(Error::<T>::Unnamed)?.1;

let err_amount = T::Currency::unreserve(&sender, deposit.clone());
debug_assert!(err_amount.is_zero());

Self::deposit_event(RawEvent::NameCleared(sender, deposit));
Self::deposit_event(Event::<T>::NameCleared(sender, deposit));
Ok(().into())
}

/// Remove an account's name and take charge of the deposit.
Expand All @@ -198,8 +197,11 @@ decl_module! {
/// - One storage read/write.
/// - One event.
/// # </weight>
#[weight = 70_000_000]
fn kill_name(origin, target: <T::Lookup as StaticLookup>::Source) {
#[pallet::weight(70_000_000)]
pub(super) fn kill_name(
origin: OriginFor<T>,
target: <T::Lookup as StaticLookup>::Source
) -> DispatchResultWithPostInfo {
T::ForceOrigin::ensure_origin(origin)?;

// Figure out who we're meant to be clearing.
Expand All @@ -209,7 +211,8 @@ decl_module! {
// Slash their deposit from them.
T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0);

Self::deposit_event(RawEvent::NameKilled(target, deposit));
Self::deposit_event(Event::<T>::NameKilled(target, deposit));
Ok(().into())
}

/// Set a third-party account's name with no deposit.
Expand All @@ -224,15 +227,20 @@ decl_module! {
/// - One storage read/write.
/// - One event.
/// # </weight>
#[weight = 70_000_000]
fn force_name(origin, target: <T::Lookup as StaticLookup>::Source, name: Vec<u8>) {
#[pallet::weight(70_000_000)]
pub(super) fn force_name(
origin: OriginFor<T>,
target: <T::Lookup as StaticLookup>::Source,
name: Vec<u8>
) -> DispatchResultWithPostInfo {
T::ForceOrigin::ensure_origin(origin)?;

let target = T::Lookup::lookup(target)?;
let deposit = <NameOf<T>>::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero);
<NameOf<T>>::insert(&target, (name, deposit));

Self::deposit_event(RawEvent::NameForced(target));
Self::deposit_event(Event::<T>::NameForced(target));
Ok(().into())
}
}
}
Expand Down Expand Up @@ -308,8 +316,8 @@ mod tests {
}
parameter_types! {
pub const ReservationFee: u64 = 2;
pub const MinLength: usize = 3;
pub const MaxLength: usize = 16;
pub const MinLength: u32 = 3;
pub const MaxLength: u32 = 16;
}
ord_parameter_types! {
pub const One: u64 = 1;
Expand Down