#![cfg_attr(not(feature = "std"), no_std)]
pub mod ctype_entry;
pub mod default_weights;
#[cfg(any(feature = "mock", test))]
pub mod mock;
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking;
#[cfg(test)]
mod tests;
pub use crate::{default_weights::WeightInfo, pallet::*};
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::{
pallet_prelude::*,
sp_runtime::traits::Hash,
traits::{
fungible::{Balanced, Credit, Inspect},
tokens::{Fortitude, Precision, Preservation},
OnUnbalanced, StorageVersion,
},
};
use frame_system::pallet_prelude::*;
use kilt_support::traits::CallSources;
use sp_runtime::SaturatedConversion;
use sp_std::vec::Vec;
use crate::ctype_entry::CtypeEntry;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
pub type CtypeHashOf<T> = <T as frame_system::Config>::Hash;
pub type CtypeEntryOf<T> = CtypeEntry<<T as Config>::CtypeCreatorId, BlockNumberFor<T>>;
pub type CtypeCreatorOf<T> = <T as Config>::CtypeCreatorId;
pub(crate) type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
pub(crate) type BalanceOf<T> = <<T as Config>::Currency as Inspect<AccountIdOf<T>>>::Balance;
type CreditOf<T> = Credit<<T as frame_system::Config>::AccountId, <T as Config>::Currency>;
#[pallet::config]
pub trait Config: frame_system::Config {
type EnsureOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::OriginSuccess>;
type OverarchingOrigin: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
type OriginSuccess: CallSources<AccountIdOf<Self>, CtypeCreatorOf<Self>>;
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type Currency: Balanced<AccountIdOf<Self>>;
type WeightInfo: WeightInfo;
type CtypeCreatorId: Parameter + MaxEncodedLen;
type Fee: Get<BalanceOf<Self>>;
type FeeCollector: OnUnbalanced<CreditOf<Self>>;
}
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::storage]
#[pallet::getter(fn ctypes)]
pub type Ctypes<T> = StorageMap<_, Blake2_128Concat, CtypeHashOf<T>, CtypeEntryOf<T>>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
CTypeCreated(CtypeCreatorOf<T>, CtypeHashOf<T>),
CTypeUpdated(CtypeHashOf<T>),
}
#[pallet::error]
pub enum Error<T> {
NotFound,
AlreadyExists,
UnableToPayFees,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(<T as pallet::Config>::WeightInfo::add(ctype.len().saturated_into()))]
pub fn add(origin: OriginFor<T>, ctype: Vec<u8>) -> DispatchResult {
let source = <T as Config>::EnsureOrigin::ensure_origin(origin)?;
let creator = source.subject();
let payer = source.sender();
let balance = <T::Currency as Inspect<AccountIdOf<T>>>::reducible_balance(
&payer,
Preservation::Preserve,
Fortitude::Polite,
);
ensure!(balance >= T::Fee::get(), Error::<T>::UnableToPayFees);
let hash = <T as frame_system::Config>::Hashing::hash(&ctype[..]);
ensure!(!Ctypes::<T>::contains_key(hash), Error::<T>::AlreadyExists);
let imbalance = <T::Currency as Balanced<AccountIdOf<T>>>::withdraw(
&payer,
T::Fee::get(),
Precision::Exact,
Preservation::Protect,
Fortitude::Polite,
)
.map_err(|_| Error::<T>::UnableToPayFees)?;
T::FeeCollector::on_unbalanced(imbalance);
log::debug!("Creating CType with hash {:?} and creator {:?}", hash, creator);
Ctypes::<T>::insert(
hash,
CtypeEntryOf::<T> {
creator: creator.clone(),
created_at: frame_system::Pallet::<T>::block_number(),
},
);
Self::deposit_event(Event::CTypeCreated(creator, hash));
Ok(())
}
#[pallet::call_index(1)]
#[pallet::weight(<T as pallet::Config>::WeightInfo::set_block_number())]
pub fn set_block_number(
origin: OriginFor<T>,
ctype_hash: CtypeHashOf<T>,
block_number: BlockNumberFor<T>,
) -> DispatchResult {
T::OverarchingOrigin::ensure_origin(origin)?;
Ctypes::<T>::try_mutate(ctype_hash, |ctype_entry| {
if let Some(ctype_entry) = ctype_entry {
ctype_entry.created_at = block_number;
Ok(())
} else {
Err(Error::<T>::NotFound)
}
})?;
Self::deposit_event(Event::CTypeUpdated(ctype_hash));
Ok(())
}
}
}