This is largely copy paste from the Basic example pallet refactor. A lot of useful information is contained there which should really be reference documentation. I've taken these out and put them here until we have a process for reference docs. I've tried to organize them under headings to suggest the type of reference docs each piece should live under. // # References // // ## Storage // // 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<T> = StorageValue<_, u32, OptionQuery>`: // - `Foo::put(1); Foo::get()` returns `Some(1)`; // - `Foo::kill(); Foo::get()` returns `None`. // - for `type Foo<T> = StorageValue<_, u32, ValueQuery>`: // - `Foo::put(1); Foo::get()` returns `1`; // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). // // The getter attribute generates a function on the `Pallet` placeholder to retrieve a value in storage: // `fn getter_name() -> Type` for basic value items or // `fn getter_name(key: KeyType) -> ValueType` for map items. // // ## Pallet call types // // Since Calls are 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. // // ## Types of calls // // 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 callable functions 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: // // ```nocompile // fn foo(origin: OriginFor<T>, bar: Bar, baz: Baz) -> DispatchResultWithPostInfo { ... }` // ``` // // Each call must define a `#[pallet::weight(..)]` attribute to convey a set of // static information about its dispatch. The 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 `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`. // // ## Helper functions // // A pallet can contain additional associated functions in its implementation block. // These fall into three broad categories: // // - Public interface "inspector" functions. These can be called by other pallets, for e.g. to check // some storage value. // - Public "operation" functions. These could be used by other pallets to perform some storage operation. // - Private functions. These are your usual private utilities unavailable to other pallets.