diff --git a/Cargo.lock b/Cargo.lock index 4d949c70..e53f7a23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2145,6 +2145,23 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-example-basic" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-fruniques" version = "0.1.0-dev" diff --git a/Cargo.toml b/Cargo.toml index c2a02c1b..76c07fe8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,23 @@ +[workspace.package] +authors = ["Hashed Pallet { ensure!(is_admin_or_owner || offer.creator_id == who, Error::::Unauthorized); match offer.status { - OfferStatus::CREATED => { + OfferStatus::Created => { >::try_mutate(order_id, |offer| -> DispatchResult { let offer = offer.as_mut().ok_or(Error::::OfferNotFound)?; offer.cancellation_date = pallet_gated_marketplace::Pallet::::get_timestamp_in_milliseconds(); - offer.status = OfferStatus::CANCELLED; + offer.status = OfferStatus::Cancelled; Ok(()) })?; Ok(()) }, - OfferStatus::TF_PENDING_SIGNATURE => { + OfferStatus::PendingTFSignature => { >::try_mutate(order_id, |offer| -> DispatchResult { let offer = offer.as_mut().ok_or(Error::::OfferNotFound)?; offer.cancellation_date = pallet_gated_marketplace::Pallet::::get_timestamp_in_milliseconds(); - offer.status = OfferStatus::CANCELLED; + offer.status = OfferStatus::Cancelled; Ok(()) })?; Ok(()) diff --git a/pallets/afloat/src/lib.rs b/pallets/afloat/src/lib.rs index 7bbf98f7..5e522f1e 100644 --- a/pallets/afloat/src/lib.rs +++ b/pallets/afloat/src/lib.rs @@ -15,12 +15,11 @@ pub mod types; pub mod pallet { use frame_support::{ pallet_prelude::*, - traits::{Currency, Time}, + traits::Currency, }; use frame_system::{pallet_prelude::*, RawOrigin}; use pallet_fruniques::types::{Attributes, CollectionDescription, FruniqueRole, ParentInfo}; use pallet_gated_marketplace::types::*; - use sp_runtime::traits::Scale; const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); use crate::types::*; diff --git a/pallets/afloat/src/mock.rs b/pallets/afloat/src/mock.rs index b3edb9bb..0295d541 100644 --- a/pallets/afloat/src/mock.rs +++ b/pallets/afloat/src/mock.rs @@ -9,7 +9,6 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; use frame_system::EnsureRoot; use system::EnsureSigned; diff --git a/pallets/afloat/src/types.rs b/pallets/afloat/src/types.rs index 4b5dc017..e8b575bb 100644 --- a/pallets/afloat/src/types.rs +++ b/pallets/afloat/src/types.rs @@ -72,21 +72,21 @@ pub enum SignUpArgs { Encode, Decode, Clone, Eq, PartialEq, RuntimeDebugNoBound, MaxEncodedLen, TypeInfo, Copy, )] pub enum OfferStatus { - CREATED, - MATCHED, - TF_FILLED, - TF_PENDING_SIGNATURE, - TF_SIGNED, - TF_SUBMITTED, - TF_APPROVED, - APPROVED, - FILLED, - CANCELLED, + Created, + Matched, + FilledByTF, + PendingTFSignature, + SignedTF, + SubmittedTF, + ApprovedTF, + Approved, + Filled, + Cancelled, } impl Default for OfferStatus { fn default() -> Self { - OfferStatus::CREATED + OfferStatus::Created } } diff --git a/pallets/bitcoin-vaults/Cargo.toml b/pallets/bitcoin-vaults/Cargo.toml index ff18ca2a..f4345f1a 100644 --- a/pallets/bitcoin-vaults/Cargo.toml +++ b/pallets/bitcoin-vaults/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "pallet-bitcoin-vaults" -version = "4.0.0-dev" description = "" -authors = ["Hashed ::dummy(), Some(value)) + } + + // An example method that returns a Result that can be called within a benchmark + fn example_result_method() -> Result<(), BenchmarkError> { + Ok(()) + } + + // This will measure the execution time of `accumulate_dummy`. + // The benchmark execution phase is shorthanded. When the name of the benchmark case is the same + // as the extrinsic call. `_(...)` is used to represent the extrinsic name. + // The benchmark verification phase is omitted. + #[benchmark] + fn accumulate_dummy() -> Result<(), BenchmarkError> { + let value = 1000u32.into(); + // The caller account is whitelisted for DB reads/write by the benchmarking macro. + let caller: T::AccountId = whitelisted_caller(); + + // an example of calling something result-based within a benchmark using the ? operator + // this necessitates specifying the `Result<(), BenchmarkError>` return type + example_result_method()?; + + // You can use `_` if the name of the Call matches the benchmark name. + #[extrinsic_call] + _(RawOrigin::Signed(caller), value); + + // need this to be compatible with the return type + Ok(()) + } + + /// You can write helper functions in here since its a normal Rust module. + fn setup_vector(len: u32) -> Vec { + let mut vector = Vec::::new(); + for i in (0..len).rev() { + vector.push(i); + } + vector + } + + // This will measure the execution time of sorting a vector. + // + // Define `x` as a linear component with range `[0, =10_000]`. This means that the benchmarking + // will assume that the weight grows at a linear rate depending on `x`. + #[benchmark] + fn sort_vector(x: Linear<0, 10_000>) { + let mut vector = setup_vector(x); + + // The benchmark execution phase could also be a closure with custom code: + #[block] + { + vector.sort(); + } + + // Check that it was sorted correctly. This will not be benchmarked and is just for + // verification. + vector.windows(2).for_each(|w| assert!(w[0] <= w[1])); + } + + // This line generates test cases for benchmarking, and could be run by: + // `cargo test -p pallet-example-basic --all-features`, you will see one line per case: + // `test benchmarking::bench_sort_vector ... ok` + // `test benchmarking::bench_accumulate_dummy ... ok` + // `test benchmarking::bench_set_dummy_benchmark ... ok` in the result. + // + // The line generates three steps per benchmark, with repeat=1 and the three steps are + // [low, mid, high] of the range. + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/pallets/example-basic/src/lib.rs b/pallets/example-basic/src/lib.rs new file mode 100644 index 00000000..5eff7492 --- /dev/null +++ b/pallets/example-basic/src/lib.rs @@ -0,0 +1,542 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Basic Example Pallet +//! +//! A pallet demonstrating concepts, APIs and structures common to most FRAME runtimes. +//! +//! **This pallet serves as an example and is not meant to be used in production.** +//! +//! > Made with *Substrate*, for *Polkadot*. +//! +//! [![github]](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/examples/basic) +//! [![polkadot]](https://polkadot.network) +//! +//! [polkadot]: https://img.shields.io/badge/polkadot-E6007A?style=for-the-badge&logo=polkadot&logoColor=white +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! +//! ## Pallet API +//! +//! See the [`pallet`] module for more information about the interfaces this pallet exposes, +//! including its configuration trait, dispatchables, storage items, events and errors. +//! +//! ## Overview +//! +//! This pallet provides basic examples of using: +//! +//! - A custom weight calculator able to classify a call's dispatch class (see: +//! [`frame_support::dispatch::DispatchClass`]) +//! - Pallet hooks to implement some custom logic that's executed before and after a block is +//! imported (see: [`frame_support::traits::Hooks`]) +//! - Inherited weight annotation for pallet calls, used to create less repetition for calls that +//! use the [`Config::WeightInfo`] trait to calculate call weights. This can also be overridden, +//! as demonstrated by [`Call::set_dummy`]. +//! - A private function that performs a storage update. +//! - A simple signed extension implementation (see: [`sp_runtime::traits::SignedExtension`]) which +//! increases the priority of the [`Call::set_dummy`] if it's present and drops any transaction +//! with an encoded length higher than 200 bytes. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use frame_support::{ + dispatch::{ClassifyDispatch, DispatchClass, DispatchResult, Pays, PaysFee, WeighData}, + traits::IsSubType, + weights::Weight, +}; +use frame_system::ensure_signed; +use log::info; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Bounded, DispatchInfoOf, SaturatedConversion, Saturating, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + }, +}; +use sp_std::{marker::PhantomData, prelude::*}; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[cfg(test)] +mod tests; + +mod benchmarking; +pub mod weights; +pub use weights::*; + +/// A type alias for the balance type from this pallet's point of view. +type BalanceOf = ::Balance; +const MILLICENTS: u32 = 1_000_000_000; + +// A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines +// the arguments and makes a decision based upon them. +// +// The `WeightData` trait has access to the arguments of the dispatch that it wants to assign a +// weight to. Nonetheless, the trait itself cannot make any assumptions about what the generic type +// of the arguments (`T`) is. Based on our needs, we could replace `T` with a more concrete type +// while implementing the trait. The `pallet::weight` expects whatever implements `WeighData` to +// replace `T` with a tuple of the dispatch arguments. This is exactly how we will craft the +// implementation below. +// +// The rules of `WeightForSetDummy` are as follows: +// - The final weight of each dispatch is calculated as the argument of the call multiplied by the +// parameter given to the `WeightForSetDummy`'s constructor. +// - assigns a dispatch class `operational` if the argument of the call is more than 1000. +// +// More information can be read at: +// - https://docs.substrate.io/main-docs/build/tx-weights-fees/ +// +// Manually configuring weight is an advanced operation and what you really need may well be +// fulfilled by running the benchmarking toolchain. Refer to `benchmarking.rs` file. +struct WeightForSetDummy(BalanceOf); + +impl WeighData<(&BalanceOf,)> for WeightForSetDummy { + fn weigh_data(&self, target: (&BalanceOf,)) -> Weight { + let multiplier = self.0; + // *target.0 is the amount passed into the extrinsic + let cents = *target.0 / >::from(MILLICENTS); + Weight::from_parts((cents * multiplier).saturated_into::(), 0) + } +} + +impl ClassifyDispatch<(&BalanceOf,)> for WeightForSetDummy { + fn classify_dispatch(&self, target: (&BalanceOf,)) -> DispatchClass { + if *target.0 > >::from(1000u32) { + DispatchClass::Operational + } else { + DispatchClass::Normal + } + } +} + +impl PaysFee<(&BalanceOf,)> for WeightForSetDummy { + fn pays_fee(&self, _target: (&BalanceOf,)) -> Pays { + Pays::Yes + } +} + +// Definition of the pallet logic, to be aggregated at runtime definition through +// `construct_runtime`. +#[frame_support::pallet] +pub mod pallet { + // Import various types used to declare pallet in scope. + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// Our pallet's configuration trait. All our types and constants go in here. If the + /// pallet is dependent on specific other pallets, then their configuration traits + /// should be added to our implied traits list. + /// + /// `frame_system::Config` should always be included. + #[pallet::config] + pub trait Config: pallet_balances::Config + frame_system::Config { + // Setting a constant config parameter from the runtime + #[pallet::constant] + type MagicNumber: Get; + + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Type representing the weight of this pallet + type WeightInfo: WeightInfo; + } + + // Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and + // method. + #[pallet::pallet] + pub struct Pallet(_); + + // This pallet implements the [`frame_support::traits::Hooks`] trait to define some logic to + // execute in some context. + #[pallet::hooks] + impl Hooks> for Pallet { + // `on_initialize` is executed at the beginning of the block before any extrinsic are + // dispatched. + // + // This function must return the weight consumed by `on_initialize` and `on_finalize`. + fn on_initialize(_n: BlockNumberFor) -> Weight { + // Anything that needs to be done at the start of the block. + // We don't do anything here. + Weight::zero() + } + + // `on_finalize` is executed at the end of block after all extrinsic are dispatched. + fn on_finalize(_n: BlockNumberFor) { + // Perform necessary data/state clean up here. + } + + // A runtime code run after every block and have access to extended set of APIs. + // + // For instance you can generate extrinsics for the upcoming produced block. + fn offchain_worker(_n: BlockNumberFor) { + // We don't do anything here. + // but we could dispatch extrinsic (transaction/unsigned/inherent) using + // sp_io::submit_extrinsic. + // To see example on offchain worker, please refer to example-offchain-worker pallet + // accompanied in this repository. + } + } + + // The call declaration. This states the entry points that we handle. The + // macro takes care of the marshalling of arguments and dispatch. + // + // Anyone can have these functions execute by signing and submitting + // an extrinsic. Ensure that calls into each of these execute in a time, memory and + // using storage space proportional to any costs paid for by the caller or otherwise the + // difficulty of forcing the call to happen. + // + // Generally you'll want to split these into three groups: + // - Public calls that are signed by an external account. + // - Root calls that are allowed to be made only by the governance system. + // - Unsigned calls that can be of two kinds: + // * "Inherent extrinsics" that are opinions generally held by the block authors that build + // child blocks. + // * Unsigned Transactions that are of intrinsic recognizable utility to the network, and are + // validated by the runtime. + // + // Information about where this dispatch initiated from is provided as the first argument + // "origin". As such functions must always look like: + // + // `fn foo(origin: OriginFor, bar: Bar, baz: Baz) -> DispatchResultWithPostInfo { ... }` + // + // The `DispatchResultWithPostInfo` is required as part of the syntax (and can be found at + // `pallet_prelude::DispatchResultWithPostInfo`). + // + // There are three entries in the `frame_system::Origin` enum that correspond + // to the above bullets: `::Signed(AccountId)`, `::Root` and `::None`. You should always match + // against them as the first thing you do in your function. There are three convenience calls + // in system that do the matching for you and return a convenient result: `ensure_signed`, + // `ensure_root` and `ensure_none`. + #[pallet::call(weight(::WeightInfo))] + impl Pallet { + /// This is your public interface. Be extremely careful. + /// This is just a simple example of how to interact with the pallet from the external + /// world. + // This just increases the value of `Dummy` by `increase_by`. + // + // Since this is a dispatched function there are two extremely important things to + // remember: + // + // - MUST NOT PANIC: Under no circumstances (save, perhaps, storage getting into an + // irreparably damaged state) must this function panic. + // - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return + // `Ok(())` or it must have no side-effects on storage and return `Err('Some reason')`. + // + // The first is relatively easy to audit for - just ensure all panickers are removed from + // logic that executes in production (which you do anyway, right?!). To ensure the second + // is followed, you should do all tests for validity at the top of your function. This + // is stuff like checking the sender (`origin`) or that state is such that the operation + // makes sense. + // + // Once you've determined that it's all good, then enact the operation and change storage. + // If you can't be certain that the operation will succeed without substantial computation + // then you have a classic blockchain attack scenario. The normal way of managing this is + // to attach a bond to the operation. As the first major alteration of storage, reserve + // some value from the sender's account (`Balances` Pallet has a `reserve` function for + // exactly this scenario). This amount should be enough to cover any costs of the + // substantial execution in case it turns out that you can't proceed with the operation. + // + // If it eventually transpires that the operation is fine and, therefore, that the + // expense of the checks should be borne by the network, then you can refund the reserved + // deposit. If, however, the operation turns out to be invalid and the computation is + // wasted, then you can burn it or repatriate elsewhere. + // + // Security bonds ensure that attackers can't game it by ensuring that anyone interacting + // with the system either progresses it or pays for the trouble of faffing around with + // no progress. + // + // If you don't respect these rules, it is likely that your chain will be attackable. + // + // Each transaction must define a `#[pallet::weight(..)]` attribute to convey a set of + // static information about its dispatch. FRAME System and FRAME Executive pallet then use + // this information to properly execute the transaction, whilst keeping the total load of + // the chain in a moderate rate. + // + // The parenthesized value of the `#[pallet::weight(..)]` attribute can be any type that + // implements a set of traits, namely [`WeighData`], [`ClassifyDispatch`], and + // [`PaysFee`]. The first conveys the weight (a numeric representation of pure + // execution time and difficulty) of the transaction and the second demonstrates the + // [`DispatchClass`] of the call, the third gives whereas extrinsic must pay fees or not. + // A higher weight means a larger transaction (less of which can be placed in a single + // block). + // + // The weight for this extrinsic we rely on the auto-generated `WeightInfo` from the + // benchmark toolchain. + #[pallet::call_index(0)] + pub fn accumulate_dummy(origin: OriginFor, increase_by: T::Balance) -> DispatchResult { + // This is a public call, so we ensure that the origin is some signed account. + let _sender = ensure_signed(origin)?; + + // Read the value of dummy from storage. + // let dummy = Self::dummy(); + // Will also work using the `::get` on the storage item type itself: + // let dummy = >::get(); + + // Calculate the new value. + // let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); + + // Put the new value into storage. + // >::put(new_dummy); + // Will also work with a reference: + // >::put(&new_dummy); + + // Here's the new one of read and then modify the value. + >::mutate(|dummy| { + // Using `saturating_add` instead of a regular `+` to avoid overflowing + let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); + *dummy = Some(new_dummy); + }); + + // Let's deposit an event to let the outside world know this happened. + Self::deposit_event(Event::AccumulateDummy { balance: increase_by }); + + // All good, no refund. + Ok(()) + } + + /// A privileged call; in this case it resets our dummy value to something new. + // Implementation of a privileged call. The `origin` parameter is ROOT because + // it's not (directly) from an extrinsic, but rather the system as a whole has decided + // to execute it. Different runtimes have different reasons for allow privileged + // calls to be executed - we don't need to care why. Because it's privileged, we can + // assume it's a one-off operation and substantial processing/storage/memory can be used + // without worrying about gameability or attack scenarios. + // + // The weight for this extrinsic we use our own weight object `WeightForSetDummy` to + // determine its weight + #[pallet::call_index(1)] + #[pallet::weight(WeightForSetDummy::(>::from(100u32)))] + pub fn set_dummy( + origin: OriginFor, + #[pallet::compact] new_value: T::Balance, + ) -> DispatchResult { + ensure_root(origin)?; + + // Print out log or debug message in the console via log::{error, warn, info, debug, + // trace}, accepting format strings similar to `println!`. + // https://paritytech.github.io/substrate/master/sp_io/logging/fn.log.html + // https://paritytech.github.io/substrate/master/frame_support/constant.LOG_TARGET.html + info!("New value is now: {:?}", new_value); + + // Put the new value into storage. + >::put(new_value); + + Self::deposit_event(Event::SetDummy { balance: new_value }); + + // All good, no refund. + Ok(()) + } + } + + /// Events are a simple means of reporting specific conditions and + /// circumstances that have happened that users, Dapps and/or chain explorers would find + /// interesting and otherwise difficult to detect. + #[pallet::event] + /// This attribute generate the function `deposit_event` to deposit one of this pallet event, + /// it is optional, it is also possible to provide a custom implementation. + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // Just a normal `enum`, here's a dummy event to ensure it compiles. + /// Dummy event, just here so there's a generic type that's used. + AccumulateDummy { + balance: BalanceOf, + }, + SetDummy { + balance: BalanceOf, + }, + SetBar { + account: T::AccountId, + balance: BalanceOf, + }, + } + + // pallet::storage attributes allow for type-safe usage of the Substrate storage database, + // so you can keep things around between blocks. + // + // Any storage must be one of `StorageValue`, `StorageMap` or `StorageDoubleMap`. + // The first generic holds the prefix to use and is generated by the macro. + // The query kind is either `OptionQuery` (the default) or `ValueQuery`. + // - for `type Foo = StorageValue<_, u32, OptionQuery>`: + // - `Foo::put(1); Foo::get()` returns `Some(1)`; + // - `Foo::kill(); Foo::get()` returns `None`. + // - for `type Foo = StorageValue<_, u32, ValueQuery>`: + // - `Foo::put(1); Foo::get()` returns `1`; + // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). + #[pallet::storage] + // The getter attribute generate a function on `Pallet` placeholder: + // `fn getter_name() -> Type` for basic value items or + // `fn getter_name(key: KeyType) -> ValueType` for map items. + #[pallet::getter(fn dummy)] + pub(super) type Dummy = StorageValue<_, T::Balance>; + + // A map that has enumerable entries. + #[pallet::storage] + #[pallet::getter(fn bar)] + pub(super) type Bar = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>; + + // this one uses the query kind: `ValueQuery`, we'll demonstrate the usage of 'mutate' API. + #[pallet::storage] + #[pallet::getter(fn foo)] + pub(super) type Foo = StorageValue<_, T::Balance, ValueQuery>; + + #[pallet::storage] + pub type CountedMap = CountedStorageMap<_, Blake2_128Concat, u8, u16>; + + // The genesis config type. + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + pub dummy: T::Balance, + pub bar: Vec<(T::AccountId, T::Balance)>, + pub foo: T::Balance, + } + + // The build of genesis for the pallet. + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + >::put(&self.dummy); + for (a, b) in &self.bar { + >::insert(a, b); + } + >::put(&self.foo); + } + } +} + +// The main implementation block for the pallet. Functions here fall into three broad +// categories: +// - Public interface. These are functions that are `pub` and generally fall into inspector +// functions that do not write to storage and operation functions that do. +// - Private functions. These are your usual private utilities unavailable to other pallets. +impl Pallet { + // Add public immutables and private mutables. + #[allow(dead_code)] + fn accumulate_foo(origin: T::RuntimeOrigin, increase_by: T::Balance) -> DispatchResult { + let _sender = ensure_signed(origin)?; + + let prev = >::get(); + // Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an + // Option<> type. + let result = >::mutate(|foo| { + *foo = foo.saturating_add(increase_by); + *foo + }); + assert!(prev + increase_by == result); + + Ok(()) + } +} + +// Similar to other FRAME pallets, your pallet can also define a signed extension and perform some +// checks and [pre/post]processing [before/after] the transaction. A signed extension can be any +// decodable type that implements `SignedExtension`. See the trait definition for the full list of +// bounds. As a convention, you can follow this approach to create an extension for your pallet: +// - If the extension does not carry any data, then use a tuple struct with just a `marker` +// (needed for the compiler to accept `T: Config`) will suffice. +// - Otherwise, create a tuple struct which contains the external data. Of course, for the entire +// struct to be decodable, each individual item also needs to be decodable. +// +// Note that a signed extension can also indicate that a particular data must be present in the +// _signing payload_ of a transaction by providing an implementation for the `additional_signed` +// method. This example will not cover this type of extension. See `CheckSpecVersion` in +// [FRAME System](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/system#signed-extensions) +// for an example. +// +// Using the extension, you can add some hooks to the life cycle of each transaction. Note that by +// default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum +// variant is given to each function of `SignedExtension`. Hence, you can filter based on pallet or +// a particular call if needed. +// +// Some extra information, such as encoded length, some static dispatch info like weight and the +// sender of the transaction (if signed) are also provided. +// +// The full list of hooks that can be added to a signed extension can be found +// [here](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html). +// +// The signed extensions are aggregated in the runtime file of a substrate chain. All extensions +// should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` +// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and +// `node-template` for an example of this. + +/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the +/// priority and prints some log. +/// +/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No +/// particular reason why, just to demonstrate the power of signed extensions. +#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[scale_info(skip_type_params(T))] +pub struct WatchDummy(PhantomData); + +impl sp_std::fmt::Debug for WatchDummy { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "WatchDummy") + } +} + +impl SignedExtension for WatchDummy +where + ::RuntimeCall: IsSubType>, +{ + const IDENTIFIER: &'static str = "WatchDummy"; + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + // if the transaction is too big, just drop it. + if len > 200 { + return InvalidTransaction::ExhaustsResources.into() + } + + // check for `set_dummy` + match call.is_sub_type() { + Some(Call::set_dummy { .. }) => { + sp_runtime::print("set_dummy was received."); + + let valid_tx = + ValidTransaction { priority: Bounded::max_value(), ..Default::default() }; + Ok(valid_tx) + }, + _ => Ok(Default::default()), + } + } +} diff --git a/pallets/example-basic/src/tests.rs b/pallets/example-basic/src/tests.rs new file mode 100644 index 00000000..c7b5b9e9 --- /dev/null +++ b/pallets/example-basic/src/tests.rs @@ -0,0 +1,198 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for pallet-example-basic. + +use crate::*; +use frame_support::{ + assert_ok, + dispatch::{DispatchInfo, GetDispatchInfo}, + traits::{ConstU64, OnInitialize}, +}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; +// Reexport crate as its pallet name for construct_runtime. +use crate as pallet_example_basic; + +type Block = frame_system::mocking::MockBlock; + +// For testing the pallet, we construct a mock runtime. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Example: pallet_example_basic::{Pallet, Call, Storage, Config, Event}, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Nonce = u64; + type Hash = H256; + type RuntimeCall = RuntimeCall; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type RuntimeFreezeReason = (); + type MaxHolds = (); +} + +impl Config for Test { + type MagicNumber = ConstU64<1_000_000_000>; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = RuntimeGenesisConfig { + // We use default for brevity, but you can configure as desired if needed. + system: Default::default(), + balances: Default::default(), + example: pallet_example_basic::GenesisConfig { + dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], + foo: 24, + }, + } + .build_storage() + .unwrap(); + t.into() +} + +#[test] +fn it_works_for_optional_value() { + new_test_ext().execute_with(|| { + // Check that GenesisBuilder works properly. + let val1 = 42; + let val2 = 27; + assert_eq!(Example::dummy(), Some(val1)); + + // Check that accumulate works when we have Some value in Dummy already. + assert_ok!(Example::accumulate_dummy(RuntimeOrigin::signed(1), val2)); + assert_eq!(Example::dummy(), Some(val1 + val2)); + + // Check that accumulate works when we Dummy has None in it. + >::on_initialize(2); + assert_ok!(Example::accumulate_dummy(RuntimeOrigin::signed(1), val1)); + assert_eq!(Example::dummy(), Some(val1 + val2 + val1)); + }); +} + +#[test] +fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + assert_eq!(Example::foo(), 24); + assert_ok!(Example::accumulate_foo(RuntimeOrigin::signed(1), 1)); + assert_eq!(Example::foo(), 25); + }); +} + +#[test] +fn set_dummy_works() { + new_test_ext().execute_with(|| { + let test_val = 133; + assert_ok!(Example::set_dummy(RuntimeOrigin::root(), test_val.into())); + assert_eq!(Example::dummy(), Some(test_val)); + }); +} + +#[test] +fn signed_ext_watch_dummy_works() { + new_test_ext().execute_with(|| { + let call = pallet_example_basic::Call::set_dummy { new_value: 10 }.into(); + let info = DispatchInfo::default(); + + assert_eq!( + WatchDummy::(PhantomData) + .validate(&1, &call, &info, 150) + .unwrap() + .priority, + u64::MAX, + ); + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, &info, 250), + InvalidTransaction::ExhaustsResources.into(), + ); + }) +} + +#[test] +fn counted_map_works() { + new_test_ext().execute_with(|| { + assert_eq!(CountedMap::::count(), 0); + CountedMap::::insert(3, 3); + assert_eq!(CountedMap::::count(), 1); + }) +} + +#[test] +fn weights_work() { + // must have a defined weight. + let default_call = pallet_example_basic::Call::::accumulate_dummy { increase_by: 10 }; + let info1 = default_call.get_dispatch_info(); + // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` + // TODO: account for proof size weight + assert!(info1.weight.ref_time() > 0); + assert_eq!(info1.weight, ::WeightInfo::accumulate_dummy()); + + // `set_dummy` is simpler than `accumulate_dummy`, and the weight + // should be less. + let custom_call = pallet_example_basic::Call::::set_dummy { new_value: 20 }; + let info2 = custom_call.get_dispatch_info(); + // TODO: account for proof size weight + assert!(info1.weight.ref_time() > info2.weight.ref_time()); +} diff --git a/pallets/example-basic/src/weights.rs b/pallets/example-basic/src/weights.rs new file mode 100644 index 00000000..def94405 --- /dev/null +++ b/pallets/example-basic/src/weights.rs @@ -0,0 +1,95 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for pallet_example_basic +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-10-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Shawns-MacBook-Pro.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/substrate +// benchmark +// pallet +// --chain=dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=pallet_example_basic +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=./ +// --template +// ./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_example_basic. +pub trait WeightInfo { + fn set_dummy_benchmark() -> Weight; + fn accumulate_dummy() -> Weight; + fn sort_vector(x: u32, ) -> Weight; +} + +/// Weights for pallet_example_basic using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: BasicExample Dummy (r:0 w:1) + fn set_dummy_benchmark() -> Weight { + Weight::from_parts(19_000_000 as u64, 0) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: BasicExample Dummy (r:1 w:1) + fn accumulate_dummy() -> Weight { + Weight::from_parts(18_000_000 as u64, 0) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + /// The range of component `x` is `[0, 10000]`. + fn sort_vector(x: u32, ) -> Weight { + Weight::from_parts(0 as u64, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(520 as u64, 0).saturating_mul(x as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: BasicExample Dummy (r:0 w:1) + fn set_dummy_benchmark() -> Weight { + Weight::from_parts(19_000_000 as u64, 0) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: BasicExample Dummy (r:1 w:1) + fn accumulate_dummy() -> Weight { + Weight::from_parts(18_000_000 as u64, 0) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + /// The range of component `x` is `[0, 10000]`. + fn sort_vector(x: u32, ) -> Weight { + Weight::from_parts(0 as u64, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(520 as u64, 0).saturating_mul(x as u64)) + } +} diff --git a/pallets/fruniques/Cargo.toml b/pallets/fruniques/Cargo.toml index 4a83df0c..8b7768cf 100644 --- a/pallets/fruniques/Cargo.toml +++ b/pallets/fruniques/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "pallet-fruniques" -version = "0.1.0-dev" description = "Fractionalized NFTs compatible with the Statemine parachain" -authors = ["Hashed ; use frame_system::EnsureRoot; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, IdentifyAccount, NumberFor, Verify}, - transaction_validity::{TransactionSource, TransactionValidity}, - AccountId32, ApplyExtrinsicResult, BuildStorage, MultiSignature, Percent, -}; +use sp_runtime::BuildStorage; use system::EnsureSigned; -type AccountId = u64; type AssetId = u32; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( diff --git a/pallets/mapped-assets/Cargo.toml b/pallets/mapped-assets/Cargo.toml index 9c259a03..1b9dcc20 100644 --- a/pallets/mapped-assets/Cargo.toml +++ b/pallets/mapped-assets/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "pallet-mapped-assets" -version = "4.0.0-dev" -authors = ["Parity Technologies "] -edition = "2021" -license = "Apache-2.0" -homepage = "https://substrate.io" -repository = "https://github.com/hashed-io/hashed-pallets" description = "FRAME asset management pallet" +version = "4.0.0-dev" +authors.workspace = true +homepage.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true readme = "README.md" [package.metadata.docs.rs] diff --git a/pallets/mapped-assets/src/lib.rs b/pallets/mapped-assets/src/lib.rs index e5622ad1..7327e4c2 100644 --- a/pallets/mapped-assets/src/lib.rs +++ b/pallets/mapped-assets/src/lib.rs @@ -181,7 +181,6 @@ use pallet_rbac::types::RoleBasedAccessControl; pub use weights::WeightInfo; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; -const LOG_TARGET: &str = "runtime::assets"; /// Trait with callbacks that are executed after successfull asset creation or destruction. pub trait AssetsCallback { diff --git a/pallets/rbac/Cargo.toml b/pallets/rbac/Cargo.toml index 193d2d70..74dcf7e8 100644 --- a/pallets/rbac/Cargo.toml +++ b/pallets/rbac/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "pallet-rbac" -version = "4.0.0-dev" description = "FRAME pallet template for defining custom runtime logic." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" -edition = "2021" -license = "MIT" -publish = false -repository = "https://github.com/hashed-io/hashed-pallets" +version = "4.0.0-dev" +authors.workspace = true +homepage.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/pallets/template/Cargo.toml b/pallets/template/Cargo.toml deleted file mode 100644 index a4e07e33..00000000 --- a/pallets/template/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -[package] -name = "pallet-template" -version = "4.0.0-dev" -description = "FRAME pallet template for defining custom runtime logic." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" -edition = "2021" -license = "Unlicense" -publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = [ - "derive", -] } -frame-support = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } -frame-system = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } -frame-benchmarking = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1", optional = true } -sp-std = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } - -[dev-dependencies] -sp-core = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } -sp-io = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } -sp-std = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "v1.3.0-rc1" } - -[features] -default = ["std"] -std = [ - "codec/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "frame-benchmarking/std", - "sp-std/std", -] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] -try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/template/src/benchmarking.rs b/pallets/template/src/benchmarking.rs deleted file mode 100644 index d496a9fc..00000000 --- a/pallets/template/src/benchmarking.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Benchmarking setup for pallet-template - -use super::*; - -#[allow(unused)] -use crate::Pallet as Template; -use frame_benchmarking::{benchmarks, whitelisted_caller}; -use frame_system::RawOrigin; - -benchmarks! { - do_something { - let s in 0 .. 100; - let caller: T::AccountId = whitelisted_caller(); - }: _(RawOrigin::Signed(caller), s) - verify { - assert_eq!(Something::::get(), Some(s)); - } - - impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); -} diff --git a/pallets/template/src/lib.rs b/pallets/template/src/lib.rs deleted file mode 100644 index c5f778a2..00000000 --- a/pallets/template/src/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -/// All migrations. -pub mod migrations; - -#[frame_support::pallet] -pub mod pallet { - - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); - - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - } - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - - pub struct Pallet(_); - - // The pallet's runtime storage items. - // https://docs.substrate.io/v3/runtime/storage - #[pallet::storage] - #[pallet::getter(fn something)] - // Learn more about declaring storage items: - // https://docs.substrate.io/v3/runtime/storage#declaring-storage-items - pub type Something = StorageValue<_, u32>; - - #[pallet::storage] - #[pallet::getter(fn my_bytes_val)] - pub type MyBytesVal = StorageValue<_, MyBytes, ValueQuery>; - - // Pallets use events to inform users when important changes are made. - // https://docs.substrate.io/v3/runtime/events-and-errors - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Event documentation should end with an array that provides descriptive names for event - /// parameters. [something, who] - SomethingStored(u32, T::AccountId), - } - - pub type MyBytes = BoundedVec>; - - // Errors inform users that something went wrong. - #[pallet::error] - pub enum Error { - /// Error names should be descriptive. - NoneValue, - /// Errors should have helpful documentation associated with them. - StorageOverflow, - } - - // Dispatchable functions allows users to interact with the pallet and invoke state changes. - // These functions materialize as "extrinsics", which are often compared to transactions. - // Dispatchable functions must be annotated with a weight and must return a DispatchResult. - #[pallet::call] - impl Pallet { - /// An example dispatchable that takes a singles value as a parameter, writes the value to - /// storage and emits an event. This function must be dispatched by a signed extrinsic. - #[pallet::call_index(0)] - #[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))] - pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { - // Check that the extrinsic was signed and get the signer. - // This function will return an error if the extrinsic is not signed. - // https://docs.substrate.io/v3/runtime/origins - let who = ensure_signed(origin)?; - - // Update storage. - >::put(something); - - // Emit an event. - Self::deposit_event(Event::SomethingStored(something, who)); - // Return a successful DispatchResultWithPostInfo - Ok(()) - } - - /// An example dispatchable that may throw a custom error. - #[pallet::call_index(1)] - #[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().reads_writes(1,1))] - pub fn cause_error(origin: OriginFor) -> DispatchResult { - let _who = ensure_signed(origin)?; - - // Read a value from storage. - match >::get() { - // Return an error if the value has not been set. - None => Err(Error::::NoneValue)?, - Some(old) => { - // Increment the value read from storage; will error in the event of overflow. - let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; - // Update the value in storage with the incremented result. - >::put(new); - Ok(()) - }, - } - } - - #[pallet::call_index(2)] - #[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))] - pub fn insert_my_bytes( - origin: OriginFor, - optional_bytes: Option, - ) -> DispatchResult { - // Check that the extrinsic was signed and get the signer. - // This function will return an error if the extrinsic is not signed. - // https://docs.substrate.io/v3/runtime/origins - let _ = ensure_signed(origin)?; - - // Update storage. - let s = optional_bytes.unwrap_or_default(); - >::put(s); - // Return a successful DispatchResultWithPostInfo - Ok(()) - } - } -} diff --git a/pallets/template/src/migrations/mod.rs b/pallets/template/src/migrations/mod.rs deleted file mode 100644 index add68f67..00000000 --- a/pallets/template/src/migrations/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ - -//! All migrations of this pallet. - -/// Version 2. -pub mod v2; diff --git a/pallets/template/src/migrations/v2.rs b/pallets/template/src/migrations/v2.rs deleted file mode 100644 index 10c0874a..00000000 --- a/pallets/template/src/migrations/v2.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Migrations to version [`2.0.0`], as denoted by the changelog. - -use frame_support::{ - traits::{Get, StorageVersion}, - weights::Weight, -}; -use frame_support::sp_runtime::traits::Zero; - -/// The old prefix. -pub const OLD_PREFIX: &[u8] = b"Template"; - -/// Some checks prior to migration. This can be linked to -/// [`frame_support::traits::OnRuntimeUpgrade::pre_upgrade`] for further testing. -/// -/// Panics if anything goes wrong. -pub fn pre_migration>(new: N) { - let new = new.as_ref(); - log::info!("pre-migration for the template pallet v2 = {}", new); - - // ensure storage version is 3. - assert_eq!(StorageVersion::get::>(), 1); -} - -/// Migrate the entire storage of this pallet to a new prefix. -/// -/// This new prefix must be the same as the one set in construct_runtime. For safety, use -/// `PalletInfo` to get it, as: -/// `::PalletInfo::name::