fix: Complete snowbridge pezpallet rebrand and critical bug fixes

- snowbridge-pezpallet-* → pezsnowbridge-pezpallet-* (201 refs)
- pallet/ directories → pezpallet/ (4 locations)
- Fixed pezpallet.rs self-include recursion bug
- Fixed sc-chain-spec hardcoded crate name in derive macro
- Reverted .pezpallet_by_name() to .pallet_by_name() (subxt API)
- Added BizinikiwiConfig type alias for zombienet tests
- Deleted obsolete session state files

Verified: pezsnowbridge-pezpallet-*, pezpallet-staking,
pezpallet-staking-async, pezframe-benchmarking-cli all pass cargo check
This commit is contained in:
2025-12-16 09:57:23 +03:00
parent 7fce5a2472
commit 90fd044766
3019 changed files with 41780 additions and 24101 deletions
@@ -20,18 +20,18 @@
//! Each of the formats is explained in [_chain-spec-format_][`pezsc_chain_spec#chain-spec-formats`].
//!
//!
//! # `GenesisConfig` for `pallet`
//! # `GenesisConfig` for `pezpallet`
//!
//! Every frame pallet may have its initial state which is defined by the `GenesisConfig` internal
//! struct. It is a regular Rust struct, annotated with the [`pallet::genesis_config`] attribute.
//! Every frame pezpallet may have its initial state which is defined by the `GenesisConfig` internal
//! struct. It is a regular Rust struct, annotated with the [`pezpallet::genesis_config`] attribute.
#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar_GenesisConfig)]
//!
//! The struct shall be defined within the pallet `mod`, as in the following code:
//! The struct shall be defined within the pezpallet `mod`, as in the following code:
#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar)]
//!
//! The initial state conveyed in the `GenesisConfig` struct is transformed into state storage
//! items by means of the [`BuildGenesisConfig`] trait, which shall be implemented for the pallet's
//! `GenesisConfig` struct. The [`pallet::genesis_build`] attribute shall be attached to the `impl`
//! items by means of the [`BuildGenesisConfig`] trait, which shall be implemented for the pezpallet's
//! `GenesisConfig` struct. The [`pezpallet::genesis_build`] attribute shall be attached to the `impl`
//! block:
#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar_build)]
//!
@@ -51,7 +51,7 @@
//!
//! # `GenesisConfig` for `runtimes`
//!
//! The runtime genesis config struct consists of configs for every pallet. For the [_demonstration
//! The runtime genesis config struct consists of configs for every pezpallet. For the [_demonstration
//! runtime_][`pez_chain_spec_guide_runtime`] used in this guide, it consists of `SystemConfig`,
//! `BarConfig`, and `FooConfig`. This structure was automatically generated by a macro and it can
//! be sneak-peeked here: [`RuntimeGenesisConfig`]. For further reading on generated runtime
@@ -189,8 +189,8 @@
//! [`impl_runtime_apis`]: frame::runtime::prelude::impl_runtime_apis
//! [`build_state`]: pezframe_support::genesis_builder_helper::build_state
//! [`get_preset`]: pezframe_support::genesis_builder_helper::get_preset
//! [`pallet::genesis_build`]: pezframe_support::pezpallet_macros::genesis_build
//! [`pallet::genesis_config`]: pezframe_support::pezpallet_macros::genesis_config
//! [`pezpallet::genesis_build`]: pezframe_support::pezpallet_macros::genesis_build
//! [`pezpallet::genesis_config`]: pezframe_support::pezpallet_macros::genesis_config
//! [`build_struct_json_patch`]: pezframe_support::build_struct_json_patch
//! [`BuildGenesisConfig`]: pezframe_support::traits::BuildGenesisConfig
//! [`serde`]: https://serde.rs/field-attrs.html
@@ -21,28 +21,28 @@ use alloc::vec::Vec;
use frame::prelude::*;
#[docify::export]
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_bar {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pallet::storage]
#[pezpallet::storage]
pub(super) type InitialAccount<T: Config> = StorageValue<Value = T::AccountId>;
/// Simple `GenesisConfig`.
#[pallet::genesis_config]
#[pezpallet::genesis_config]
#[derive(DefaultNoBound)]
#[docify::export(pezpallet_bar_GenesisConfig)]
pub struct GenesisConfig<T: Config> {
pub initial_account: Option<T::AccountId>,
}
#[pallet::genesis_build]
#[pezpallet::genesis_build]
#[docify::export(pezpallet_bar_build)]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
/// The storage building function that presents a direct mapping of the initial config
@@ -94,24 +94,24 @@ pub enum FooEnum {
}
#[docify::export]
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_foo {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pallet::storage]
#[pezpallet::storage]
pub type ProcessedEnumValue<T> = StorageValue<Value = u64>;
#[pallet::storage]
#[pezpallet::storage]
pub type SomeInteger<T> = StorageValue<Value = u32>;
/// The more sophisticated structure for conveying initial state.
#[docify::export(pezpallet_foo_GenesisConfig)]
#[pallet::genesis_config]
#[pezpallet::genesis_config]
#[derive(DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
pub some_integer: u32,
@@ -121,7 +121,7 @@ pub mod pezpallet_foo {
pub _phantom: PhantomData<T>,
}
#[pallet::genesis_build]
#[pezpallet::genesis_build]
#[docify::export(pezpallet_foo_build)]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
/// The build method that indirectly maps an initial config values into the storage items.
@@ -67,15 +67,15 @@ mod runtime {
)]
pub struct Runtime;
/// Mandatory system pallet that should always be included in a FRAME runtime.
/// Mandatory system pezpallet that should always be included in a FRAME runtime.
#[runtime::pezpallet_index(0)]
pub type System = pezframe_system;
/// Sample pallet 1
/// Sample pezpallet 1
#[runtime::pezpallet_index(1)]
pub type Bar = pezpallet_bar;
/// Sample pallet 2
/// Sample pezpallet 2
#[runtime::pezpallet_index(2)]
pub type Foo = pezpallet_foo;
}
@@ -84,7 +84,7 @@ parameter_types! {
pub const Version: RuntimeVersion = VERSION;
}
/// Implements the types required for the system pallet.
/// Implements the types required for the system pezpallet.
#[derive_impl(pezframe_system::config_preludes::SolochainDefaultConfig)]
impl pezframe_system::Config for Runtime {
type Block = Block;
@@ -214,7 +214,7 @@
//!
//! #### Bob's Overflowed Balance
//!
//! **Bob's** balance exceeds the `Balance` type on the `EduChain`. Because the pallet developer did
//! **Bob's** balance exceeds the `Balance` type on the `EduChain`. Because the pezpallet developer did
//! not handle the calculation to add to Bob's balance with any regard to this overflow, **Bob's**
//! balance is now essentially `0`, the operation **wrapped**.
//!
@@ -247,7 +247,7 @@
//!
//! A `u8` parameter, called `proposals_count`, represents the type for counting the number of
//! proposals on-chain. Every time a new proposal is added to the system, this number increases.
//! With the proposal pallet's high usage, it has reached `u8::MAX`s limit of 255, causing
//! With the proposal pezpallet's high usage, it has reached `u8::MAX`s limit of 255, causing
//! `proposals_count` to go to 0. Unfortunately, this results in new proposals overwriting old ones,
//! effectively erasing any notion of past proposals!
//!
@@ -276,7 +276,7 @@
//! authoring, consensus, or other protocol-level dependencies, going through with an action may
//! actually cause harm to the network, and thus stalling would be the better option.
//!
//! Take the example of the BABE pallet ([`pezpallet_babe`]), which doesn't allow for a validator to
//! Take the example of the BABE pezpallet ([`pezpallet_babe`]), which doesn't allow for a validator to
//! participate if it is disabled (see: [`frame::traits::DisabledValidators`]):
//!
//! ```ignore
@@ -155,7 +155,7 @@
//!
//! A call can be anything that implements [`Encode`][frame::deps::codec::Encode]. In FRAME-based
//! runtimes, a call is represented as an enum of enums, where the outer enum represents the FRAME
//! pallet being called, and the inner enum represents the call being made within that pallet, and
//! pezpallet being called, and the inner enum represents the call being made within that pezpallet, and
//! any arguments to it. Read more about the call enum
//! [here][crate::reference_docs::frame_runtime_types].
//!
@@ -172,15 +172,15 @@
//! )
//! ```
//!
//! - `pezpallet_index` is a single byte denoting the index of the pallet that we are calling into, and
//! - `pezpallet_index` is a single byte denoting the index of the pezpallet that we are calling into, and
//! is what the tag of the outermost enum will encode to.
//! - `call_index` is a single byte denoting the index of the call that we are making the pallet,
//! - `call_index` is a single byte denoting the index of the call that we are making the pezpallet,
//! and is what the tag of the inner enum will encode to.
//! - `call_args` are the SCALE encoded bytes for each of the arguments that the call expects, and
//! are typically provided as values to the inner enum.
//!
//! Information about the pallets that exist for a chain (including their indexes), the calls
//! available in each pallet (including their indexes), and the arguments required for each call can
//! available in each pezpallet (including their indexes), and the arguments required for each call can
//! be found in the metadata for the chain. For V15 metadata, this information [is
//! here][frame::deps::pezframe_support::__private::metadata::v15::PalletMetadata].
//!
@@ -219,7 +219,7 @@
//! in the [Checkable](pezsp_runtime::traits::Checkable) implementation of
//! [UncheckedExtrinsic](pezsp_runtime::generic::UncheckedExtrinsic). Therefore, it is up to each
//! extension to define the format of the payload it will try to check and authorize the right
//! origin type. For an example, look into the [authorization example pallet
//! origin type. For an example, look into the [authorization example pezpallet
//! extensions](pezpallet_example_authorization_tx_extension::extensions)
//!
//! # Example Encoding
@@ -245,7 +245,7 @@ pub mod call_data {
}
// An inner enum represents the calls within
// a specific pallet. "PalletA" has one call,
// a specific pezpallet. "PalletA" has one call,
// "Foo".
#[derive(Encode, Decode, Clone)]
pub enum PalletACall {
@@ -47,7 +47,7 @@
//! the 20ms. In a benchmarked environment, it can examine the transactions for their upper bound,
//! and include the ones that are known to fit based on the worst case.
//!
//! The benchmarking code can be written as a part of FRAME pallet, using the macros provided in
//! The benchmarking code can be written as a part of FRAME pezpallet, using the macros provided in
//! [`pezframe_benchmarking`]. See any of the existing pallets in `pezkuwi-sdk`, or the pallets in our
//! [`crate::pezkuwi_sdk::templates`] for examples.
//!
@@ -72,12 +72,12 @@
//! If this block of code is to be benchmarked, then the benchmarking code must be written such that
//! it captures the worst case.
//!
//! ## Gluing Pallet Benchmarking with Runtime
//! ## Gluing Pezpallet Benchmarking with Runtime
//!
//! FRAME pallets are mandated to provide their own benchmarking code. Runtimes contain the
//! boilerplate needed to run these benchmarking (see [Running Benchmarks
//! below](#running-benchmarks)). The outcome of running these benchmarks are meant to be fed back
//! into the pallet via a conventional `trait WeightInfo` on `Config`:
//! into the pezpallet via a conventional `trait WeightInfo` on `Config`:
#![doc = docify::embed!("src/reference_docs/pezframe_benchmarking_weight.rs", WeightInfo)]
//!
//! Then, individual functions of this trait are the final values that we assigned to the
@@ -130,9 +130,9 @@
//! [PolkaVM]: https://github.com/koute/polkavm
//! [JAM]: https://graypaper.com
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
#[allow(unused_variables, unreachable_code, unused, clippy::diverging_sub_expression)]
pub mod pallet {
pub mod pezpallet {
use frame::prelude::*;
#[docify::export]
@@ -140,18 +140,18 @@ pub mod pallet {
fn simple_transfer() -> Weight;
}
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
type WeightInfo: WeightInfo;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
#[docify::export]
#[pallet::weight(10_000)]
#[pezpallet::weight(10_000)]
pub fn simple_transfer(
origin: OriginFor<T>,
destination: T::AccountId,
@@ -167,7 +167,7 @@ pub mod pallet {
}
#[docify::export]
#[pallet::weight(T::WeightInfo::simple_transfer())]
#[pezpallet::weight(T::WeightInfo::simple_transfer())]
pub fn simple_transfer_2(
origin: OriginFor<T>,
destination: T::AccountId,
@@ -184,7 +184,7 @@ pub mod pallet {
#[docify::export]
// This is the worst-case, pre-dispatch weight.
#[pallet::weight(T::WeightInfo::simple_transfer())]
#[pezpallet::weight(T::WeightInfo::simple_transfer())]
pub fn simple_transfer_3(
origin: OriginFor<T>,
destination: T::AccountId,
+13 -13
View File
@@ -17,15 +17,15 @@
//! }
//! ```
//!
//! within the pallet, if you want to use the standard `println!`, it needs to be wrapped in
//! within the pezpallet, if you want to use the standard `println!`, it needs to be wrapped in
//! [`pezsp_std::if_std`]. Of course, this means that this print code is only available to you in the
//! `std` compiler flag, and never present in a wasm build.
//!
//! ```
//! // somewhere in your pallet. This is not a real pallet code.
//! mod pallet {
//! struct Pallet;
//! impl Pallet {
//! // somewhere in your pezpallet. This is not a real pezpallet code.
//! mod pezpallet {
//! struct Pezpallet;
//! impl Pezpallet {
//! fn print() {
//! pezsp_std::if_std! {
//! println!("Hello, world!");
@@ -42,9 +42,9 @@
//! 1. `log-level`, signifying how important it is.
//! 2. `log-target`, signifying to which component it belongs.
//!
//! Add log statements to your pallet as such:
//! Add log statements to your pezpallet as such:
//!
//! You can add the log crate to the `Cargo.toml` of the pallet.
//! You can add the log crate to the `Cargo.toml` of the pezpallet.
//!
//! ```text
//! #[dependencies]
@@ -59,14 +59,14 @@
//!
//! More conveniently, the `frame` umbrella crate re-exports the log crate as [`frame::log`].
//!
//! Then, the pallet can use this crate to emit log statements. In this statement, we use the info
//! Then, the pezpallet can use this crate to emit log statements. In this statement, we use the info
//! level, and the target is `pezpallet-example`.
//!
//! ```
//! mod pallet {
//! struct Pallet;
//! mod pezpallet {
//! struct Pezpallet;
//!
//! impl Pallet {
//! impl Pezpallet {
//! fn logs() {
//! frame::log::info!(target: "pezpallet-example", "Hello, world!");
//! }
@@ -81,7 +81,7 @@
//! // in your test
//! fn it_also_prints() {
//! pezsp_api::init_runtime_logger();
//! // call into your pallet, and now it will print `log` statements.
//! // call into your pezpallet, and now it will print `log` statements.
//! }
//! ```
//!
@@ -107,7 +107,7 @@
//! ## Log Target Prefixing
//!
//! Many [`crate::pezkuwi_sdk::frame_runtime`] pallets emit logs with log target `runtime::<name of
//! pallet>`, for example `runtime::system`. This then allows one to run a node with a wasm blob
//! pezpallet>`, for example `runtime::system`. This then allows one to run a node with a wasm blob
//! compiled with `LOG_TARGET=runtime=debug`, which enables the log target of all pallets who's log
//! target starts with `runtime`.
//!
@@ -58,18 +58,18 @@
//! [`frame::pezpallet_macros::hooks`].
//!
//! ```
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! use frame::prelude::*;
//!
//! #[pallet::config]
//! #[pezpallet::config]
//! pub trait Config: pezframe_system::Config {}
//!
//! #[pallet::pallet]
//! pub struct Pallet<T>(_);
//! #[pezpallet::pezpallet]
//! pub struct Pezpallet<T>(_);
//!
//! #[pallet::hooks]
//! impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
//! #[pezpallet::hooks]
//! impl<T: Config> Hooks<BlockNumberFor<T>> for Pezpallet<T> {
//! fn offchain_worker(block_number: BlockNumberFor<T>) {
//! // ...
//! }
+32 -32
View File
@@ -31,7 +31,7 @@
//!
//! ## Context
//!
//! First, let's look at where the `origin` type is encountered in a typical pallet. The `origin:
//! First, let's look at where the `origin` type is encountered in a typical pezpallet. The `origin:
//! OriginFor<T>` has to be the first argument of any given callable extrinsic in FRAME:
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", call_simple)]
//!
@@ -44,12 +44,12 @@
//! amalgamated at the runtime level. Read [`crate::reference_docs::frame_runtime_types`] to
//! familiarize yourself with these types.
//!
//! To understand this better, we will next create a pallet with a custom origin, which will add a
//! To understand this better, we will next create a pezpallet with a custom origin, which will add a
//! new variant to `RuntimeOrigin`.
//!
//! ## Adding Custom Pallet Origin to the Runtime
//! ## Adding Custom Pezpallet Origin to the Runtime
//!
//! For example, given a pallet that defines the following custom origin:
//! For example, given a pezpallet that defines the following custom origin:
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin)]
//!
//! And a runtime with the following pallets:
@@ -57,7 +57,7 @@
//!
//! The type [`crate::reference_docs::frame_origin::runtime_for_origin::RuntimeOrigin`] is expanded.
//! This `RuntimeOrigin` contains a variant for the [`pezframe_system::RawOrigin`] and the custom
//! origin of the pallet.
//! origin of the pezpallet.
//!
//! > Notice how the [`pezframe_system::ensure_signed`] is nothing more than a `match` statement. If
//! > you want to know where the actual origin of an extrinsic is set (and the signature
@@ -67,30 +67,30 @@
//!
//! ## Asserting on a Custom Internal Origin
//!
//! In order to assert on a custom origin that is defined within your pallet, we need a way to first
//! In order to assert on a custom origin that is defined within your pezpallet, we need a way to first
//! convert the `<T as pezframe_system::Config>::RuntimeOrigin` into the local `enum Origin` of the
//! current pallet. This is a common process that is explained in
//! current pezpallet. This is a common process that is explained in
//! [`crate::reference_docs::frame_runtime_types#
//! adding-further-constraints-to-runtime-composite-enums`].
//!
//! We use the same process here to express that `RuntimeOrigin` has a number of additional bounds,
//! as follows.
//!
//! 1. Defining a custom `RuntimeOrigin` with further bounds in the pallet.
//! 1. Defining a custom `RuntimeOrigin` with further bounds in the pezpallet.
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin_bound)]
//!
//! 2. Using it in the pallet.
//! 2. Using it in the pezpallet.
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin_usage)]
//!
//! ## Asserting on a Custom External Origin
//!
//! Very often, a pallet wants to have a parameterized origin that is **NOT** defined within the
//! pallet. In other words, a pallet wants to delegate an origin check to something that is
//! Very often, a pezpallet wants to have a parameterized origin that is **NOT** defined within the
//! pezpallet. In other words, a pezpallet wants to delegate an origin check to something that is
//! specified later at the runtime level. Like many other parameterizations in FRAME, this implies
//! adding a new associated type to `trait Config`.
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", external_origin_def)]
//!
//! Then, within the pallet, we can simply use this "unknown" origin check type:
//! Then, within the pezpallet, we can simply use this "unknown" origin check type:
#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", external_origin_usage)]
//!
//! Finally, at the runtime, any implementation of [`frame::traits::EnsureOrigin`] can be passed.
@@ -112,7 +112,7 @@
//! ## Obtaining Abstract Origins
//!
//! So far we have learned that FRAME pallets can assert on custom and abstract origin types,
//! whether they are defined within the pallet or not. But how can we obtain these abstract origins?
//! whether they are defined within the pezpallet or not. But how can we obtain these abstract origins?
//!
//! > All extrinsics that come from the outer world can generally only be obtained as either
//! > `signed` or `none` origin.
@@ -130,19 +130,19 @@
use frame::prelude::*;
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_for_origin {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(call_simple)]
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn do_something(_origin: OriginFor<T>) -> DispatchResult {
// ^^^^^^^^^^^^^^^^^^^^^
todo!();
@@ -150,23 +150,23 @@ pub mod pezpallet_for_origin {
}
}
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_with_custom_origin {
use super::*;
#[docify::export(custom_origin_bound)]
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
type RuntimeOrigin: From<<Self as pezframe_system::Config>::RuntimeOrigin>
+ Into<Result<Origin, <Self as Config>::RuntimeOrigin>>;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(custom_origin)]
/// A dummy custom origin.
#[pallet::origin]
#[pezpallet::origin]
#[derive(
PartialEq,
Eq,
@@ -186,8 +186,8 @@ pub mod pezpallet_with_custom_origin {
}
#[docify::export(custom_origin_usage)]
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn only_validators(origin: OriginFor<T>) -> DispatchResult {
// first, we convert from `<T as pezframe_system::Config>::RuntimeOrigin` to `<T as
// Config>::RuntimeOrigin`
@@ -225,21 +225,21 @@ pub mod runtime_for_origin {
}
}
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_with_external_origin {
use super::*;
#[docify::export(external_origin_def)]
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
type ExternalOrigin: EnsureOrigin<Self::RuntimeOrigin>;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(external_origin_usage)]
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn externally_checked_ext(origin: OriginFor<T>) -> DispatchResult {
T::ExternalOrigin::ensure_origin(origin)?;
todo!();
@@ -1,32 +1,32 @@
//! # FRAME Pallet Coupling
//! # FRAME Pezpallet Coupling
//!
//! This reference document explains how FRAME pallets can be combined to interact together.
//!
//! It is suggested to re-read [`crate::pezkuwi_sdk::frame_runtime`], notably the information
//! around [`frame::pezpallet_macros::config`]. Recall that:
//!
//! > Configuration trait of a pallet: It allows a pallet to receive types at a later
//! > point from the runtime that wishes to contain it. It allows the pallet to be parameterized
//! > Configuration trait of a pezpallet: It allows a pezpallet to receive types at a later
//! > point from the runtime that wishes to contain it. It allows the pezpallet to be parameterized
//! > over both types and values.
//!
//! ## Context, Background
//!
//! FRAME pallets, as per described in [`crate::pezkuwi_sdk::frame_runtime`] are:
//!
//! > A pallet is a unit of encapsulated logic. It has a clearly defined responsibility and can be
//! > A pezpallet is a unit of encapsulated logic. It has a clearly defined responsibility and can be
//! linked to other pallets.
//!
//! That is to say:
//!
//! * *encapsulated*: Ideally, a FRAME pallet contains encapsulated logic which has clear
//! boundaries. It is generally a bad idea to build a single monolithic pallet that does multiple
//! * *encapsulated*: Ideally, a FRAME pezpallet contains encapsulated logic which has clear
//! boundaries. It is generally a bad idea to build a single monolithic pezpallet that does multiple
//! things, such as handling currencies, identities and staking all at the same time.
//! * *linked to other pallets*: But, adhering extensively to the above also hinders the ability to
//! write useful applications. Pallets often need to work with each other, communicate and use
//! each other's functionalities.
//!
//! The broad principle that allows pallets to be linked together is the same way through which a
//! pallet uses its `Config` trait to receive types and values from the runtime that contains it.
//! pezpallet uses its `Config` trait to receive types and values from the runtime that contains it.
//!
//! There are generally two ways to achieve this:
//!
@@ -63,7 +63,7 @@
//!
//! ## Example
//!
//! Consider the following example, in which `pezpallet-foo` needs another pallet to provide the block
//! Consider the following example, in which `pezpallet-foo` needs another pezpallet to provide the block
//! author to it, and `pezpallet-author` which has access to this information.
#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", pezpallet_foo)]
#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", pezpallet_author)]
@@ -71,16 +71,16 @@
//! ### Tight Coupling Pallets
//!
//! To tightly couple `pezpallet-foo` and `pezpallet-author`, we use Rust's supertrait system. When a
//! pallet makes its own `trait Config` be bounded by another pallet's `trait Config`, it is
//! pezpallet makes its own `trait Config` be bounded by another pezpallet's `trait Config`, it is
//! expressing two things:
//!
//! 1. That it can only exist in a runtime if the other pallet is also present.
//! 2. That it can use the other pallet's functionality.
//! 1. That it can only exist in a runtime if the other pezpallet is also present.
//! 2. That it can use the other pezpallet's functionality.
//!
//! `pezpallet-foo`'s `Config` would then look like:
#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", tight_config)]
//!
//! And `pezpallet-foo` can use the method exposed by `pezpallet_author::Pallet` directly:
//! And `pezpallet-foo` can use the method exposed by `pezpallet_author::Pezpallet` directly:
#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", tight_usage)]
//!
//!
@@ -120,9 +120,9 @@
//!
//! ## Frame System
//!
//! With the above information in context, we can conclude that **`pezframe_system` is a special pallet
//! that is tightly coupled with every other pallet**. This is because it provides the fundamental
//! system functionality that every pallet needs, such as some types like
//! With the above information in context, we can conclude that **`pezframe_system` is a special pezpallet
//! that is tightly coupled with every other pezpallet**. This is because it provides the fundamental
//! system functionality that every pezpallet needs, such as some types like
//! [`frame::prelude::pezframe_system::Config::AccountId`],
//! [`frame::prelude::pezframe_system::Config::Hash`], and some functionality such as block number,
//! etc.
@@ -132,18 +132,18 @@
//! To recap, consider the following rules of thumb:
//!
//! * In all cases, try and break down big pallets apart with clear boundaries of responsibility. In
//! general, it is easier to argue about multiple pallet if they only communicate together via a
//! general, it is easier to argue about multiple pezpallet if they only communicate together via a
//! known trait, rather than having access to all of each others public items, such as storage and
//! dispatchables.
//! * If a group of pallets is meant to work together, but is not foreseen to be generalized, or
//! used by others, consider tightly coupling pallets, *if it simplifies the development*.
//! * If a pallet needs a functionality provided by another pallet, but multiple implementations can
//! * If a pezpallet needs a functionality provided by another pezpallet, but multiple implementations can
//! be foreseen, consider loosely coupling pallets.
//!
//! For example, all pallets in `pezkuwi-sdk` that needed to work with currencies could have been
//! tightly coupled with [`pezpallet_balances`]. But, `pezkuwi-sdk` also provides [`pezpallet_assets`]
//! (and more implementations by the community), therefore all pallets use traits to loosely couple
//! with balances or assets pallet. More on this in [`crate::reference_docs::frame_tokens`].
//! with balances or assets pezpallet. More on this in [`crate::reference_docs::frame_tokens`].
//!
//! ## Further References
//!
@@ -158,17 +158,17 @@
use frame::prelude::*;
#[docify::export]
#[frame::pallet]
#[frame::pezpallet]
pub mod pezpallet_foo {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
impl<T: Config> Pallet<T> {
impl<T: Config> Pezpallet<T> {
fn do_stuff_with_author() {
// needs block author here
}
@@ -176,41 +176,41 @@ pub mod pezpallet_foo {
}
#[docify::export]
#[frame::pallet]
#[frame::pezpallet]
pub mod pezpallet_author {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
impl<T: Config> Pallet<T> {
impl<T: Config> Pezpallet<T> {
pub fn author() -> T::AccountId {
todo!("somehow has access to the block author and can return it here")
}
}
}
#[frame::pallet]
#[frame::pezpallet]
pub mod pezpallet_foo_tight {
use super::*;
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(tight_config)]
/// This pallet can only live in a runtime that has both `pezframe_system` and `pezpallet_author`.
#[pallet::config]
/// This pezpallet can only live in a runtime that has both `pezframe_system` and `pezpallet_author`.
#[pezpallet::config]
pub trait Config: pezframe_system::Config + pezpallet_author::Config {}
#[docify::export(tight_usage)]
impl<T: Config> Pallet<T> {
impl<T: Config> Pezpallet<T> {
// anywhere in `pezpallet-foo`, we can call into `pezpallet-author` directly, namely because
// `T: pezpallet_author::Config`
fn do_stuff_with_author() {
let _ = pezpallet_author::Pallet::<T>::author();
let _ = pezpallet_author::Pezpallet::<T>::author();
}
}
}
@@ -221,23 +221,23 @@ pub trait AuthorProvider<AccountId> {
fn author() -> AccountId;
}
#[frame::pallet]
#[frame::pezpallet]
pub mod pezpallet_foo_loose {
use super::*;
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(loose_config)]
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
/// This pallet relies on the existence of something that implements [`AuthorProvider`],
/// This pezpallet relies on the existence of something that implements [`AuthorProvider`],
/// which may or may not be `pezpallet-author`.
type AuthorProvider: AuthorProvider<Self::AccountId>;
}
#[docify::export(loose_usage)]
impl<T: Config> Pallet<T> {
impl<T: Config> Pezpallet<T> {
fn do_stuff_with_author() {
let _ = T::AuthorProvider::author();
}
@@ -245,9 +245,9 @@ pub mod pezpallet_foo_loose {
}
#[docify::export(pezpallet_author_provider)]
impl<T: pezpallet_author::Config> AuthorProvider<T::AccountId> for pezpallet_author::Pallet<T> {
impl<T: pezpallet_author::Config> AuthorProvider<T::AccountId> for pezpallet_author::Pezpallet<T> {
fn author() -> T::AccountId {
pezpallet_author::Pallet::<T>::author()
pezpallet_author::Pezpallet::<T>::author()
}
}
@@ -269,7 +269,7 @@ impl<AccountId> AuthorProvider<AccountId> for () {
pub mod runtime {
use super::*;
use pezcumulus_pezpallet_aura_ext::pallet;
use pezcumulus_pezpallet_aura_ext::pezpallet;
use frame::{runtime::prelude::*, testing_prelude::*};
construct_runtime!(
@@ -289,7 +289,7 @@ pub mod runtime {
#[docify::export(runtime_author_provider)]
impl pezpallet_foo_loose::Config for Runtime {
type AuthorProvider = pezpallet_author::Pallet<Runtime>;
type AuthorProvider = pezpallet_author::Pezpallet<Runtime>;
// which is also equivalent to
// type AuthorProvider = PalletAuthor;
}
@@ -0,0 +1,296 @@
//! # FRAME Pezpallet Coupling
//!
//! This reference document explains how FRAME pezpallets can be combined to interact together.
//!
//! It is suggested to re-read [`crate::pezkuwi_sdk::frame_runtime`], notably the information
//! around [`frame::pezpallet_macros::config`]. Recall that:
//!
//! > Configuration trait of a pezpallet: It allows a pezpallet to receive types at a later
//! > point from the runtime that wishes to contain it. It allows the pezpallet to be parameterized
//! > over both types and values.
//!
//! ## Context, Background
//!
//! FRAME pezpallets, as per described in [`crate::pezkuwi_sdk::frame_runtime`] are:
//!
//! > A pezpallet is a unit of encapsulated logic. It has a clearly defined responsibility and can be
//! linked to other pezpallets.
//!
//! That is to say:
//!
//! * *encapsulated*: Ideally, a FRAME pezpallet contains encapsulated logic which has clear
//! boundaries. It is generally a bad idea to build a single monolithic pezpallet that does multiple
//! things, such as handling currencies, identities and staking all at the same time.
//! * *linked to other pezpallets*: But, adhering extensively to the above also hinders the ability to
//! write useful applications. Pezpallets often need to work with each other, communicate and use
//! each other's functionalities.
//!
//! The broad principle that allows pezpallets to be linked together is the same way through which a
//! pezpallet uses its `Config` trait to receive types and values from the runtime that contains it.
//!
//! There are generally two ways to achieve this:
//!
//! 1. Tight coupling pezpallets.
//! 2. Loose coupling pezpallets.
//!
//! To explain the difference between the two, consider two pezpallets, `A` and `B`. In both cases, `A`
//! wants to use some functionality exposed by `B`.
//!
//! When tightly coupling pezpallets, `A` can only exist in a runtime if `B` is also present in the
//! same runtime. That is, `A` is expressing that can only work if `B` is present.
//!
//! This translates to the following Rust code:
//!
//! ```
//! trait Pezpallet_B_Config {}
//! trait Pezpallet_A_Config: Pezpallet_B_Config {}
//! ```
//!
//! Contrary, when pezpallets are loosely coupled, `A` expresses that some functionality, expressed via
//! a trait `F`, needs to be fulfilled. This trait is then implemented by `B`, and the two pezpallets
//! are linked together at the runtime level. This means that `A` only relies on the implementation
//! of `F`, which may be `B`, or another implementation of `F`.
//!
//! This translates to the following Rust code:
//!
//! ```
//! trait F {}
//! trait Pezpallet_A_Config {
//! type F: F;
//! }
//! // Pezpallet_B will implement and fulfill `F`.
//! ```
//!
//! ## Example
//!
//! Consider the following example, in which `pezpallet-foo` needs another pezpallet to provide the block
//! author to it, and `pezpallet-author` which has access to this information.
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", pezpallet_foo)]
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", pezpallet_author)]
//!
//! ### Tight Coupling Pezpallets
//!
//! To tightly couple `pezpallet-foo` and `pezpallet-author`, we use Rust's supertrait system. When a
//! pezpallet makes its own `trait Config` be bounded by another pezpallet's `trait Config`, it is
//! expressing two things:
//!
//! 1. That it can only exist in a runtime if the other pezpallet is also present.
//! 2. That it can use the other pezpallet's functionality.
//!
//! `pezpallet-foo`'s `Config` would then look like:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", tight_config)]
//!
//! And `pezpallet-foo` can use the method exposed by `pezpallet_author::Pezpallet` directly:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", tight_usage)]
//!
//!
//! ### Loosely Coupling Pezpallets
//!
//! If `pezpallet-foo` wants to *not* rely on `pezpallet-author` directly, it can leverage its
//! `Config`'s associated types. First, we need a trait to express the functionality that
//! `pezpallet-foo` wants to obtain:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", AuthorProvider)]
//!
//! > We sometimes refer to such traits that help two pezpallets interact as "glue traits".
//!
//! Next, `pezpallet-foo` states that it needs this trait to be provided to it, at the runtime level,
//! via an associated type:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", loose_config)]
//!
//! Then, `pezpallet-foo` can use this trait to obtain the block author, without knowing where it comes
//! from:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", loose_usage)]
//!
//! Then, if `pezpallet-author` implements this glue-trait:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", pezpallet_author_provider)]
//!
//! And upon the creation of the runtime, the two pezpallets are linked together as such:
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", runtime_author_provider)]
//!
//! Crucially, when using loose coupling, we gain the flexibility of providing different
//! implementations of `AuthorProvider`, such that different users of a `pezpallet-foo` can use
//! different ones, without any code change being needed. For example, in the code snippets of this
//! module, you can find [`OtherAuthorProvider`], which is an alternative implementation of
//! [`AuthorProvider`].
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", other_author_provider)]
//!
//! A common pattern in pezkuwi-sdk is to provide an implementation of such glu traits for the unit
//! type as a "default/test behavior".
#![doc = docify::embed!("./src/reference_docs/frame_pezpallet_coupling.rs", unit_author_provider)]
//!
//! ## Frame System
//!
//! With the above information in context, we can conclude that **`pezframe_system` is a special pezpallet
//! that is tightly coupled with every other pezpallet**. This is because it provides the fundamental
//! system functionality that every pezpallet needs, such as some types like
//! [`frame::prelude::pezframe_system::Config::AccountId`],
//! [`frame::prelude::pezframe_system::Config::Hash`], and some functionality such as block number,
//! etc.
//!
//! ## Recap
//!
//! To recap, consider the following rules of thumb:
//!
//! * In all cases, try and break down big pezpallets apart with clear boundaries of responsibility. In
//! general, it is easier to argue about multiple pezpallet if they only communicate together via a
//! known trait, rather than having access to all of each others public items, such as storage and
//! dispatchables.
//! * If a group of pezpallets is meant to work together, but is not foreseen to be generalized, or
//! used by others, consider tightly coupling pezpallets, *if it simplifies the development*.
//! * If a pezpallet needs a functionality provided by another pezpallet, but multiple implementations can
//! be foreseen, consider loosely coupling pezpallets.
//!
//! For example, all pezpallets in `pezkuwi-sdk` that needed to work with currencies could have been
//! tightly coupled with [`pezpallet_balances`]. But, `pezkuwi-sdk` also provides [`pezpallet_assets`]
//! (and more implementations by the community), therefore all pezpallets use traits to loosely couple
//! with balances or assets pezpallet. More on this in [`crate::reference_docs::frame_tokens`].
//!
//! ## Further References
//!
//! - <https://www.youtube.com/watch?v=0eNGZpNkJk4>
//! - <https://exchange.pezkuwichain.app/questions/922/pezpallet-loose-couplingtight-coupling-and-missing-traits>
//!
//! [`AuthorProvider`]: crate::reference_docs::frame_pezpallet_coupling::AuthorProvider
//! [`OtherAuthorProvider`]: crate::reference_docs::frame_pezpallet_coupling::OtherAuthorProvider
#![allow(unused)]
use frame::prelude::*;
#[docify::export]
#[frame::pezpallet]
pub mod pezpallet_foo {
use super::*;
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
impl<T: Config> Pezpallet<T> {
fn do_stuff_with_author() {
// needs block author here
}
}
}
#[docify::export]
#[frame::pezpallet]
pub mod pezpallet_author {
use super::*;
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
impl<T: Config> Pezpallet<T> {
pub fn author() -> T::AccountId {
todo!("somehow has access to the block author and can return it here")
}
}
}
#[frame::pezpallet]
pub mod pezpallet_foo_tight {
use super::*;
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(tight_config)]
/// This pezpallet can only live in a runtime that has both `pezframe_system` and `pezpallet_author`.
#[pezpallet::config]
pub trait Config: pezframe_system::Config + pezpallet_author::Config {}
#[docify::export(tight_usage)]
impl<T: Config> Pezpallet<T> {
// anywhere in `pezpallet-foo`, we can call into `pezpallet-author` directly, namely because
// `T: pezpallet_author::Config`
fn do_stuff_with_author() {
let _ = pezpallet_author::Pezpallet::<T>::author();
}
}
}
#[docify::export]
/// Abstraction over "something that can provide the block author".
pub trait AuthorProvider<AccountId> {
fn author() -> AccountId;
}
#[frame::pezpallet]
pub mod pezpallet_foo_loose {
use super::*;
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[docify::export(loose_config)]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
/// This pezpallet relies on the existence of something that implements [`AuthorProvider`],
/// which may or may not be `pezpallet-author`.
type AuthorProvider: AuthorProvider<Self::AccountId>;
}
#[docify::export(loose_usage)]
impl<T: Config> Pezpallet<T> {
fn do_stuff_with_author() {
let _ = T::AuthorProvider::author();
}
}
}
#[docify::export(pezpallet_author_provider)]
impl<T: pezpallet_author::Config> AuthorProvider<T::AccountId> for pezpallet_author::Pezpallet<T> {
fn author() -> T::AccountId {
pezpallet_author::Pezpallet::<T>::author()
}
}
pub struct OtherAuthorProvider;
#[docify::export(other_author_provider)]
impl<AccountId> AuthorProvider<AccountId> for OtherAuthorProvider {
fn author() -> AccountId {
todo!("somehow get the block author here")
}
}
#[docify::export(unit_author_provider)]
impl<AccountId> AuthorProvider<AccountId> for () {
fn author() -> AccountId {
todo!("somehow get the block author here")
}
}
pub mod runtime {
use super::*;
use pezcumulus_pezpallet_aura_ext::pezpallet;
use frame::{runtime::prelude::*, testing_prelude::*};
construct_runtime!(
pub struct Runtime {
System: pezframe_system,
PezpalletFoo: pezpallet_foo_loose,
PezpalletAuthor: pezpallet_author,
}
);
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
impl pezframe_system::Config for Runtime {
type Block = MockBlock<Self>;
}
impl pezpallet_author::Config for Runtime {}
#[docify::export(runtime_author_provider)]
impl pezpallet_foo_loose::Config for Runtime {
type AuthorProvider = pezpallet_author::Pezpallet<Runtime>;
// which is also equivalent to
// type AuthorProvider = PezpalletAuthor;
}
}
@@ -13,7 +13,7 @@
//!
//! Many types within a FRAME runtime follow the following structure:
//!
//! * Each individual pallet defines a type, for example `Foo`.
//! * Each individual pezpallet defines a type, for example `Foo`.
//! * At the runtime level, these types are amalgamated into a single type, for example
//! `RuntimeFoo`.
//!
@@ -38,9 +38,9 @@
//! Let's explore how each of these affect the [`RuntimeCall`], [`RuntimeOrigin`] and
//! [`RuntimeGenesisConfig`] generated in [`runtime`] respectively.
//!
//! As observed, [`RuntimeCall`] has 3 variants, one for each pallet and one for `pezframe_system`. If
//! As observed, [`RuntimeCall`] has 3 variants, one for each pezpallet and one for `pezframe_system`. If
//! you explore further, you will soon realize that each variant is merely a pointer to the `Call`
//! type in each pallet, for example [`pezpallet_foo::Call`].
//! type in each pezpallet, for example [`pezpallet_foo::Call`].
//!
//! [`RuntimeOrigin`]'s [`OriginCaller`] has two variants, one for system, and one for `pezpallet_foo`
//! which utilized [`frame::pezpallet_macros::origin`].
@@ -57,7 +57,7 @@
//!
//! ### Adding Further Constraints to Runtime Composite Enums
//!
//! This section explores a common scenario where a pallet has access to one of these runtime
//! This section explores a common scenario where a pezpallet has access to one of these runtime
//! composite enums, but it wishes to further specify it by adding more trait bounds to it.
//!
//! Let's take the example of `RuntimeCall`. This is an associated type in
@@ -70,14 +70,14 @@
//! [`pezframe_system::Config::RuntimeCall`] are specifying:
#![doc = docify::embed!("../../bizinikiwi/pezframe/system/src/lib.rs", system_runtime_call)]
//!
//! So, when at a given pallet, one accesses `<T as pezframe_system::Config>::RuntimeCall`, the type is
//! So, when at a given pezpallet, one accesses `<T as pezframe_system::Config>::RuntimeCall`, the type is
//! extremely opaque from the perspective of the Rust compiler.
//!
//! How can a pallet access the `RuntimeCall` type with further constraints? For example, each
//! pallet has its own `enum Call`, and knows that its local `Call` is a part of `RuntimeCall`,
//! How can a pezpallet access the `RuntimeCall` type with further constraints? For example, each
//! pezpallet has its own `enum Call`, and knows that its local `Call` is a part of `RuntimeCall`,
//! therefore there should be a `impl From<Call<_>> for RuntimeCall`.
//!
//! The only way to express this using Rust's associated types is for the pallet to **define its own
//! The only way to express this using Rust's associated types is for the pezpallet to **define its own
//! associated type `RuntimeCall`, and further specify what it thinks `RuntimeCall` should be**.
//!
//! In this case, we will want to assert the existence of [`frame::traits::IsSubType`], which is
@@ -89,7 +89,7 @@
#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", pezpallet_with_specific_runtime_call_impl)]
//!
//! > In other words, the degree of specificity that [`pezframe_system::Config::RuntimeCall`] has is
//! > not enough for the pallet to work with. Therefore, the pallet has to define its own associated
//! > not enough for the pezpallet to work with. Therefore, the pezpallet has to define its own associated
//! > type representing `RuntimeCall`.
//!
//! Another way to look at this is:
@@ -98,7 +98,7 @@
//! are two different representations of the same concrete type that is only known when the runtime
//! is being constructed.
//!
//! Now, within this pallet, this new `RuntimeCall` can be used, and it can use its new trait
//! Now, within this pezpallet, this new `RuntimeCall` can be used, and it can use its new trait
//! bounds, such as being [`frame::traits::IsSubType`]:
#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", custom_runtime_call_usages)]
//!
@@ -123,7 +123,7 @@
//!
//! A number of type aliases are generated by the `construct_runtime` which are also noteworthy:
//!
//! * [`runtime::PalletFoo`] is an alias to [`pezpallet_foo::Pallet`]. Same for `PalletBar`, and
//! * [`runtime::PalletFoo`] is an alias to [`pezpallet_foo::Pezpallet`]. Same for `PalletBar`, and
//! `System`
//! * [`runtime::AllPalletsWithSystem`] is an alias for a tuple of all of the above. This type is
//! important to FRAME internals such as `executive`, as it implements traits such as
@@ -145,7 +145,7 @@
//! [`runtime`]: crate::reference_docs::frame_runtime_types::runtime
//! [`pezpallet_foo`]: crate::reference_docs::frame_runtime_types::pezpallet_foo
//! [`pezpallet_foo::Call`]: crate::reference_docs::frame_runtime_types::pezpallet_foo::Call
//! [`pezpallet_foo::Pallet`]: crate::reference_docs::frame_runtime_types::pezpallet_foo::Pallet
//! [`pezpallet_foo::Pezpallet`]: crate::reference_docs::frame_runtime_types::pezpallet_foo::Pezpallet
//! [`pezpallet_bar`]: crate::reference_docs::frame_runtime_types::pezpallet_bar
//! [`pezpallet_bar::GenesisConfig`]: crate::reference_docs::frame_runtime_types::pezpallet_bar::GenesisConfig
//! [`RuntimeEvent`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeEvent
@@ -160,14 +160,14 @@
use frame::prelude::*;
#[docify::export]
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_foo {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::origin]
#[pezpallet::origin]
#[derive(
PartialEq,
Eq,
@@ -184,11 +184,11 @@ pub mod pezpallet_foo {
B,
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn foo(_origin: OriginFor<T>) -> DispatchResult {
todo!();
}
@@ -200,29 +200,29 @@ pub mod pezpallet_foo {
}
#[docify::export]
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_bar {
use super::*;
#[pallet::config]
#[pezpallet::config]
pub trait Config: pezframe_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pallet::genesis_config]
#[pezpallet::genesis_config]
#[derive(DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
pub initial_account: Option<T::AccountId>,
}
#[pallet::genesis_build]
#[pezpallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn bar(_origin: OriginFor<T>) -> DispatchResult {
todo!();
}
@@ -251,41 +251,41 @@ pub mod runtime {
impl pezpallet_bar::Config for Runtime {}
}
#[frame::pallet(dev_mode)]
#[frame::pezpallet(dev_mode)]
pub mod pezpallet_with_specific_runtime_call {
use super::*;
use frame::traits::IsSubType;
#[docify::export(custom_runtime_call)]
/// A pallet that wants to further narrow down what `RuntimeCall` is.
#[pallet::config]
/// A pezpallet that wants to further narrow down what `RuntimeCall` is.
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
type RuntimeCall: IsSubType<Call<Self>>;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
// note that this pallet needs some `call` to have a `enum Call`.
#[pallet::call]
impl<T: Config> Pallet<T> {
// note that this pezpallet needs some `call` to have a `enum Call`.
#[pezpallet::call]
impl<T: Config> Pezpallet<T> {
pub fn foo(_origin: OriginFor<T>) -> DispatchResult {
todo!();
}
}
#[docify::export(custom_runtime_call_usages)]
impl<T: Config> Pallet<T> {
impl<T: Config> Pezpallet<T> {
fn _do_something_useful_with_runtime_call(call: <T as Config>::RuntimeCall) {
// check if the runtime call given is of this pallet's variant.
// check if the runtime call given is of this pezpallet's variant.
let _maybe_my_call: Option<&Call<T>> = call.is_sub_type();
todo!();
}
}
#[docify::export(assert_equality)]
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
#[pezpallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pezpallet<T> {
fn integrity_test() {
use core::any::TypeId;
assert_eq!(
@@ -39,11 +39,11 @@
//!
//! Self-contained pieces of logic that execute after a runtime upgrade are called "Migrations".
//!
//! The typical use case of a migration is to 'migrate' pallet storage from one layout to another,
//! The typical use case of a migration is to 'migrate' pezpallet storage from one layout to another,
//! for example when the encoding of a storage item is changed. However, they can also execute
//! arbitrary logic such as:
//!
//! - Calling arbitrary pallet methods.
//! - Calling arbitrary pezpallet methods.
//! - Mutating arbitrary on-chain state.
//! - Cleaning up some old storage items that are no longer needed.
//!
@@ -54,13 +54,13 @@
//! - Are suitable for migrations which are guaranteed to not exceed the block weight.
//! - Are simply implementations of [`OnRuntimeUpgrade`].
//!
//! To learn best practices for writing single block pallet storage migrations, see the
//! [Single Block Migration Example Pallet](pezpallet_example_single_block_migrations).
//! To learn best practices for writing single block pezpallet storage migrations, see the
//! [Single Block Migration Example Pezpallet](pezpallet_example_single_block_migrations).
//!
//! ### Scheduling the Single Block Migrations to Run Next Runtime Upgrade
//!
//! Schedule migrations to run next runtime upgrade passing them as a parameter to your
//! [`Config`](pezframe_system) pallet:
//! [`Config`](pezframe_system) pezpallet:
//!
//! ```ignore
//! /// Tuple of migrations (structs that implement `OnRuntimeUpgrade`)
@@ -8,16 +8,16 @@
//! Let's begin by starting to store a `NewType` in a storage item:
//!
//! ```compile_fail
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! pub struct NewType(u32);
//
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T> = StorageValue<_, NewType>;
//! }
//! ```
@@ -32,17 +32,17 @@
//! This implies the following set of traits that need to be derived for a type to be stored in
//! `frame` storage:
//! ```rust
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! #[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, scale_info::TypeInfo)]
//! pub struct NewType(u32);
//!
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T> = StorageValue<_, NewType>;
//! }
//! ```
@@ -50,17 +50,17 @@
//! Next, let's look at how this will differ if we are to store a type that is derived from `T` in
//! storage, such as [`frame::prelude::BlockNumberFor`]:
//! ```compile_fail
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! #[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, scale_info::TypeInfo)]
//! pub struct NewType<T: Config>(BlockNumberFor<T>);
//!
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, NewType<T>>;
//! }
//! ```
@@ -84,18 +84,18 @@
//! attribute to `NewType`. This additional macro will instruct the `derive` to skip the bound on
//! `T`.
//! ```rust
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! #[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, scale_info::TypeInfo)]
//! #[scale_info(skip_type_params(T))]
//! pub struct NewType<T: Config>(BlockNumberFor<T>);
//!
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, NewType<T>>;
//! }
//! ```
@@ -104,18 +104,18 @@
//! must also implement `Default`. This should be as simple as adding `derive(Default)` to it,
//! right?
//! ```compile_fail
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! #[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, scale_info::TypeInfo, Default)]
//! #[scale_info(skip_type_params(T))]
//! pub struct NewType<T: Config>(BlockNumberFor<T>);
//!
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, NewType<T>, ValueQuery>;
//! }
//! ```
@@ -142,13 +142,13 @@
//!
//! We can fix the following example by using [`frame::prelude::DefaultNoBound`].
//! ```rust
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! # use frame::prelude::*;
//! # #[pallet::config]
//! # #[pezpallet::config]
//! # pub trait Config: pezframe_system::Config {}
//! # #[pallet::pallet]
//! # pub struct Pallet<T>(_);
//! # #[pezpallet::pezpallet]
//! # pub struct Pezpallet<T>(_);
//! #[derive(
//! codec::Encode,
//! codec::Decode,
@@ -159,7 +159,7 @@
//! #[scale_info(skip_type_params(T))]
//! pub struct NewType<T:Config>(BlockNumberFor<T>);
//!
//! #[pallet::storage]
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, NewType<T>, ValueQuery>;
//! }
//! ```
@@ -167,26 +167,26 @@
//! Finally, if a custom type that is provided through `Config` is to be stored in the storage, it
//! is subject to the same trait requirements. The following does not work:
//! ```compile_fail
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! use frame::prelude::*;
//! #[pallet::config]
//! #[pezpallet::config]
//! pub trait Config: pezframe_system::Config {
//! type CustomType;
//! }
//! #[pallet::pallet]
//! pub struct Pallet<T>(_);
//! #[pallet::storage]
//! #[pezpallet::pezpallet]
//! pub struct Pezpallet<T>(_);
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, T::CustomType>;
//! }
//! ```
//!
//! But adding the right trait bounds will fix it.
//! ```rust
//! #[frame::pallet]
//! pub mod pallet {
//! #[frame::pezpallet]
//! pub mod pezpallet {
//! use frame::prelude::*;
//! #[pallet::config]
//! #[pezpallet::config]
//! pub trait Config: pezframe_system::Config {
//! type CustomType: codec::FullCodec
//! + codec::MaxEncodedLen
@@ -194,9 +194,9 @@
//! + Debug
//! + Default;
//! }
//! #[pallet::pallet]
//! pub struct Pallet<T>(_);
//! #[pallet::storage]
//! #[pezpallet::pezpallet]
//! pub struct Pezpallet<T>(_);
//! #[pezpallet::storage]
//! pub type Something<T: Config> = StorageValue<_, T::CustomType>;
//! }
//! ```
+10 -10
View File
@@ -36,7 +36,7 @@
//! You may then write custom pallets that interact with [`pezpallet_balances`]. The fastest way to
//! get started with that is by
//! [tightly coupling](crate::reference_docs::frame_pallet_coupling#tight-coupling-pallets) your
//! custom pallet to [`pezpallet_balances`].
//! custom pezpallet to [`pezpallet_balances`].
//!
//! However, to keep pallets flexible and modular, it is often preferred to
//! [loosely couple](crate::reference_docs::frame_pallet_coupling#loosely--coupling-pallets).
@@ -70,18 +70,18 @@
//! The distinction between traits and trait implementations is helpful because it allows pallets
//! and other logic to be generic over their dependencies, avoiding tight coupling.
//!
//! To illustrate this with an example let's consider [`pezpallet_preimage`]. This pallet takes a
//! To illustrate this with an example let's consider [`pezpallet_preimage`]. This pezpallet takes a
//! deposit in exchange for storing a preimage for later use. A naive implementation of the
//! pallet may use [`pezpallet_balances`] in a tightly coupled manner, directly calling methods
//! on the pallet to reserve and unreserve deposits. This approach works well,
//! until someone has a use case requiring that an asset from a different pallet such as
//! pezpallet may use [`pezpallet_balances`] in a tightly coupled manner, directly calling methods
//! on the pezpallet to reserve and unreserve deposits. This approach works well,
//! until someone has a use case requiring that an asset from a different pezpallet such as
//! [`pezpallet_assets`] is used for the deposit. Rather than tightly coupling [`pezpallet_preimage`] to
//! [`pezpallet_balances`], [`pezpallet_assets`], and every other token-handling pallet, a user
//! could possibly specify that [`pezpallet_preimage`] does not specify a concrete pallet as a
//! [`pezpallet_balances`], [`pezpallet_assets`], and every other token-handling pezpallet, a user
//! could possibly specify that [`pezpallet_preimage`] does not specify a concrete pezpallet as a
//! dependency, but instead accepts any dependency which implements the
//! [`currency::ReservableCurrency`](`pezframe_support::traits::tokens::currency::ReservableCurrency`)
//! trait, namely via its [`Config::Currency`](`pezpallet_preimage::pallet::Config::Currency`)
//! associated type. This allows [`pezpallet_preimage`] to support any arbitrary pallet implementing
//! trait, namely via its [`Config::Currency`](`pezpallet_preimage::pezpallet::Config::Currency`)
//! associated type. This allows [`pezpallet_preimage`] to support any arbitrary pezpallet implementing
//! this trait, without needing any knowledge of what those pallets may be or requiring changes to
//! support new pallets which may be written in the future.
//!
@@ -115,7 +115,7 @@
//! ## Non-Fungible Tokens in FRAME
//!
//! [`pezpallet_nfts`] is recommended to use for all NFT use cases in FRAME.
//! See the crate documentation for more info about this pallet.
//! See the crate documentation for more info about this pezpallet.
//!
//! [`pezpallet_uniques`] is deprecated and should not be used.
//!
+2 -2
View File
@@ -66,14 +66,14 @@
//! included into a block and leads to some action. This includes user-initiated transactions as
//! well as inherents which are placed into the block by the block-builder.
//!
//! #### Pallet
//! #### Pezpallet
//!
//! Similar to software modules in traditional programming, [FRAME](frame) pallets in Bizinikiwi are
//! modular components that encapsulate distinct functionalities or business logic. Just as
//! libraries or modules are used to build and extend the capabilities of a software application,
//! pallets are the foundational building blocks for constructing a blockchain's runtime with frame.
//! They enable the creation of customizable and upgradeable networks, offering a composable
//! framework for a Bizinikiwi-based blockchain. Each pallet can be thought of as a plug-and-play
//! framework for a Bizinikiwi-based blockchain. Each pezpallet can be thought of as a plug-and-play
//! module, enhancing the blockchain's functionality in a cohesive and integrated manner.
//!
//! #### Full Node
+1 -1
View File
@@ -60,7 +60,7 @@ pub mod defensive_programming;
/// `RuntimeCall`.
pub mod frame_runtime_types;
/// Learn about how to make a pallet/runtime that is fee-less and instead uses another mechanism to
/// Learn about how to make a pezpallet/runtime that is fee-less and instead uses another mechanism to
/// control usage and sybil attacks.
pub mod fee_less_runtime;
+3 -3
View File
@@ -120,7 +120,7 @@
//!
//! In practice, the majority of the implementation of any consensus engine is in the node side, but
//! the runtime also typically needs to expose a custom runtime-api to enable the particular
//! consensus engine to work, and that particular runtime-api is implemented by a pallet
//! consensus engine to work, and that particular runtime-api is implemented by a pezpallet
//! corresponding to that consensus engine.
//!
//! For example, taking a snippet from [`pez_solochain_template_runtime`], the runtime has to provide
@@ -187,7 +187,7 @@
//! The list of checks may evolve in the future and for now only few rules are implemented:
//! * runtimes must define a type for [`pezcumulus-pezpallet-teyrchain-system`], which is recommended to
//! be named as `TeyrchainSystem`.
//! * runtimes must define a type for [`pezframe-system`] pallet, which is recommended to be named as
//! * runtimes must define a type for [`pezframe-system`] pezpallet, which is recommended to be named as
//! `System`. The configured [`block number`] here will be used by Omni Node to configure AURA
//! accordingly.
//!
@@ -198,4 +198,4 @@
//! [`chain-spec-builder`]: https://crates.io/crates/pezstaging-chain-spec-builder
//! [`pezcumulus-pezpallet-teyrchain-system`]: https://docs.rs/pezcumulus-pezpallet-parachain-system/latest/pezcumulus_pezpallet_parachain_system/
//! [`pezframe-system`]: https://docs.rs/pezframe-system/latest/pezframe_system/
//! [`block number`]: https://docs.rs/pezframe-system/latest/pezframe_system/pallet/storage_types/struct.Number.html
//! [`block number`]: https://docs.rs/pezframe-system/latest/pezframe_system/pezpallet/storage_types/struct.Number.html
@@ -9,8 +9,8 @@
//! section.
//! Moreover, we use the [`frame::traits::Get`].
//!
//! First, imagine we are writing a FRAME pallet. We represent this pallet with a `struct Pallet`,
//! and this pallet wants to implement the functionalities of that pallet, for example a simple
//! First, imagine we are writing a FRAME pezpallet. We represent this pezpallet with a `struct Pezpallet`,
//! and this pezpallet wants to implement the functionalities of that pezpallet, for example a simple
//! `transfer` function. For the sake of education, we are interested in having a `MinTransfer`
//! amount, expressed as a [`frame::traits::Get`], which will dictate what is the minimum amount
//! that can be transferred.
@@ -26,10 +26,10 @@
//! In a broad sense, there are two avenues in exposing configurability:
//!
//! 1. For *values* that need to be generic, for example `MinTransfer`, we attach them to the
//! `Pallet` struct as fields:
//! `Pezpallet` struct as fields:
//!
//! ```
//! struct Pallet {
//! struct Pezpallet {
//! min_transfer: u128,
//! }
//! ```
@@ -38,7 +38,7 @@
//! as:
//!
//! ```
//! struct Pallet<AccountId> {
//! struct Pezpallet<AccountId> {
//! min_transfer: u128,
//! _marker: std::marker::PhantomData<AccountId>,
//! }
@@ -48,13 +48,13 @@
//! use *types* to declare both *values* and *types* as generic. This is the essence of why the
//! `Get` trait exists.
//!
//! This would bring us to the second iteration of the pallet, which would look like:
//! This would bring us to the second iteration of the pezpallet, which would look like:
#![doc = docify::embed!("./src/reference_docs/trait_based_programming.rs", generic)]
//!
//! In this example, we managed to make all 3 of our types generic. Taking the example of the
//! `AccountId`, one should read the above as following:
//!
//! > The `Pallet` does not know what type `AccountId` concretely is, but it knows that it is
//! > The `Pezpallet` does not know what type `AccountId` concretely is, but it knows that it is
//! > something that adheres to being `From<[u8; 32]>`.
//!
//! This method would work, but it suffers from two downsides:
@@ -117,13 +117,13 @@ use frame::traits::Get;
#[docify::export]
mod basic {
struct Pallet;
struct Pezpallet;
type AccountId = frame::deps::pezsp_runtime::AccountId32;
type Balance = u128;
type MinTransfer = frame::traits::ConstU128<10>;
impl Pallet {
impl Pezpallet {
fn transfer(_from: AccountId, _to: AccountId, _amount: Balance) {
todo!()
}
@@ -134,11 +134,11 @@ mod basic {
mod generic {
use super::*;
struct Pallet<AccountId, Balance, MinTransfer> {
struct Pezpallet<AccountId, Balance, MinTransfer> {
_marker: std::marker::PhantomData<(AccountId, Balance, MinTransfer)>,
}
impl<AccountId, Balance, MinTransfer> Pallet<AccountId, Balance, MinTransfer>
impl<AccountId, Balance, MinTransfer> Pezpallet<AccountId, Balance, MinTransfer>
where
Balance: frame::traits::AtLeast32BitUnsigned,
MinTransfer: frame::traits::Get<Balance>,
@@ -161,8 +161,8 @@ mod trait_based {
type MinTransfer: frame::traits::Get<Self::Balance>;
}
struct Pallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pallet<T> {
struct Pezpallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pezpallet<T> {
fn transfer(_from: T::AccountId, _to: T::AccountId, amount: T::Balance) {
assert!(amount >= T::MinTransfer::get());
unimplemented!();
@@ -183,8 +183,8 @@ mod with_system {
type MinTransfer: frame::traits::Get<Self::Balance>;
}
pub struct Pallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pallet<T> {
pub struct Pezpallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pezpallet<T> {
fn transfer(_from: T::AccountId, _to: T::AccountId, amount: T::Balance) {
assert!(amount >= T::MinTransfer::get());
unimplemented!();
@@ -213,8 +213,8 @@ mod fully_qualified_complicated {
type Currency: CurrencyTrait;
}
struct Pallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pallet<T> {
struct Pezpallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> Pezpallet<T> {
fn transfer(
_from: T::AccountId,
_to: T::AccountId,