,
21 | /// Transaction pool instance.
22 | pub pool: Arc,
23 | /// Whether to deny unsafe calls
24 | pub deny_unsafe: DenyUnsafe,
25 | /// A command stream to send authoring commands to manual seal consensus engine
26 | pub command_sink: Sender>,
27 | }
28 |
29 | /// Instantiate all full RPC extensions.
30 | pub fn create_full(deps: FullDeps) -> jsonrpc_core::IoHandler
31 | where
32 | C: ProvideRuntimeApi,
33 | C: HeaderBackend + HeaderMetadata + 'static,
34 | C: Send + Sync + 'static,
35 | C::Api: BlockBuilder,
36 | C::Api: sum_storage_runtime_api::SumStorageApi,
37 | P: TransactionPool + 'static,
38 | {
39 | let mut io = jsonrpc_core::IoHandler::default();
40 | let FullDeps {
41 | command_sink,
42 | client,
43 | ..
44 | } = deps;
45 |
46 | // Add a silly RPC that returns constant values
47 | io.extend_with(crate::silly_rpc::SillyRpc::to_delegate(
48 | crate::silly_rpc::Silly {},
49 | ));
50 |
51 | // Add a second RPC extension
52 | // Because this one calls a Runtime API it needs a reference to the client.
53 | io.extend_with(sum_storage_rpc::SumStorageApi::to_delegate(
54 | sum_storage_rpc::SumStorage::new(client),
55 | ));
56 |
57 | // The final RPC extension receives commands for the manual seal consensus engine.
58 | io.extend_with(
59 | // We provide the rpc handler with the sending end of the channel to allow the rpc
60 | // send EngineCommands to the background block authorship task.
61 | ManualSealApi::to_delegate(ManualSeal::new(command_sink)),
62 | );
63 |
64 | io
65 | }
66 |
--------------------------------------------------------------------------------
/nodes/rpc-node/src/silly_rpc.rs:
--------------------------------------------------------------------------------
1 | use jsonrpc_core::Result;
2 | use jsonrpc_derive::rpc;
3 |
4 | #[rpc]
5 | pub trait SillyRpc {
6 | #[rpc(name = "silly_seven")]
7 | fn silly_7(&self) -> Result;
8 |
9 | #[rpc(name = "silly_double")]
10 | fn silly_double(&self, val: u64) -> Result;
11 | }
12 |
13 | /// A struct that implements the `SillyRpc`
14 | pub struct Silly;
15 |
16 | impl SillyRpc for Silly {
17 | fn silly_7(&self) -> Result {
18 | Ok(7)
19 | }
20 |
21 | fn silly_double(&self, val: u64) -> Result {
22 | Ok(2 * val)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pallets/basic-token/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "basic-token"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A Pallet that implements a basic account-based cryptocurrency"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 |
17 | [dev-dependencies]
18 | serde = '1.0'
19 |
20 | # Substrate packages
21 | sp-core = '3.0'
22 | sp-io = '3.0'
23 | sp-runtime = '3.0'
24 |
25 | [features]
26 | default = ['std']
27 | std = [
28 | 'frame-support/std',
29 | 'frame-system/std',
30 | 'parity-scale-codec/std',
31 | ]
32 |
--------------------------------------------------------------------------------
/pallets/basic-token/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(feature = "std"), no_std)]
2 | #![allow(clippy::unused_unit)]
3 |
4 | //! Simple Token Transfer
5 | //! 1. set total supply
6 | //! 2. establish ownership upon configuration of circulating tokens
7 | //! 3. coordinate token transfers with the runtime functions
8 |
9 | pub use pallet::*;
10 |
11 | #[cfg(test)]
12 | mod tests;
13 |
14 | #[frame_support::pallet]
15 | pub mod pallet {
16 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
17 | use frame_system::pallet_prelude::*;
18 |
19 | #[pallet::config]
20 | pub trait Config: frame_system::Config {
21 | /// The overarching event type.
22 | type Event: From> + IsType<::Event>;
23 | }
24 |
25 | #[pallet::event]
26 | #[pallet::metadata(T::AccountId = "AccountId")]
27 | #[pallet::generate_deposit(pub (super) fn deposit_event)]
28 | pub enum Event {
29 | /// Token was initialized by user
30 | Initialized(T::AccountId),
31 | /// Tokens successfully transferred between users
32 | Transfer(T::AccountId, T::AccountId, u64), // (from, to, value)
33 | }
34 |
35 | #[pallet::storage]
36 | #[pallet::getter(fn get_balance)]
37 | pub(super) type Balances =
38 | StorageMap<_, Blake2_128Concat, T::AccountId, u64, ValueQuery>;
39 |
40 | #[pallet::type_value]
41 | pub(super) fn TotalSupplyDefaultValue() -> u64 {
42 | 21000000
43 | }
44 |
45 | #[pallet::storage]
46 | #[pallet::getter(fn total_supply)]
47 | pub(super) type TotalSupply =
48 | StorageValue<_, u64, ValueQuery, TotalSupplyDefaultValue>;
49 |
50 | #[pallet::storage]
51 | #[pallet::getter(fn is_init)]
52 | pub(super) type Init = StorageValue<_, bool, ValueQuery>;
53 |
54 | #[pallet::pallet]
55 | #[pallet::generate_store(pub (super) trait Store)]
56 | pub struct Pallet(PhantomData);
57 |
58 | #[pallet::hooks]
59 | impl Hooks> for Pallet {}
60 |
61 | #[pallet::error]
62 | pub enum Error {
63 | /// Attempted to initialize the token after it had already been initialized.
64 | AlreadyInitialized,
65 | /// Attempted to transfer more funds than were available
66 | InsufficientFunds,
67 | }
68 |
69 | #[pallet::call]
70 | impl Pallet {
71 | /// Initialize the token
72 | /// transfers the total_supply amout to the caller
73 | #[pallet::weight(10_000)]
74 | pub fn init(_origin: OriginFor) -> DispatchResultWithPostInfo {
75 | let sender = ensure_signed(_origin)?;
76 | ensure!(!Self::is_init(), >::AlreadyInitialized);
77 |
78 | >::insert(sender, Self::total_supply());
79 |
80 | Init::::put(true);
81 | Ok(().into())
82 | }
83 |
84 | /// Transfer tokens from one account to another
85 | #[pallet::weight(10_000)]
86 | pub fn transfer(
87 | _origin: OriginFor,
88 | to: T::AccountId,
89 | value: u64,
90 | ) -> DispatchResultWithPostInfo {
91 | let sender = ensure_signed(_origin)?;
92 | let sender_balance = Self::get_balance(&sender);
93 | let receiver_balance = Self::get_balance(&to);
94 |
95 | // Calculate new balances
96 | let updated_from_balance = sender_balance
97 | .checked_sub(value)
98 | .ok_or(>::InsufficientFunds)?;
99 | let updated_to_balance = receiver_balance
100 | .checked_add(value)
101 | .expect("Entire supply fits in u64; qed");
102 |
103 | // Write new balances to storage
104 | >::insert(&sender, updated_from_balance);
105 | >::insert(&to, updated_to_balance);
106 |
107 | Self::deposit_event(Event::Transfer(sender, to, value));
108 | Ok(().into())
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/pallets/basic-token/src/tests.rs:
--------------------------------------------------------------------------------
1 | use crate::{self as basic_token, Config, Error};
2 | use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types};
3 | use frame_system as system;
4 | use sp_core::H256;
5 | use sp_io::TestExternalities;
6 | use sp_runtime::{
7 | testing::Header,
8 | traits::{BlakeTwo256, IdentityLookup},
9 | };
10 |
11 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
12 | type Block = frame_system::mocking::MockBlock;
13 |
14 | construct_runtime!(
15 | pub enum TestRuntime where
16 | Block = Block,
17 | NodeBlock = Block,
18 | UncheckedExtrinsic = UncheckedExtrinsic,
19 | {
20 | System: frame_system::{Module, Call, Config, Storage, Event},
21 | BasicToken: basic_token::{Module, Call, Storage, Event},
22 | }
23 | );
24 |
25 | parameter_types! {
26 | pub const BlockHashCount: u64 = 250;
27 | pub BlockWeights: frame_system::limits::BlockWeights =
28 | frame_system::limits::BlockWeights::simple_max(1024);
29 | }
30 | impl frame_system::Config for TestRuntime {
31 | type BaseCallFilter = ();
32 | type BlockWeights = ();
33 | type BlockLength = ();
34 | type Origin = Origin;
35 | type Index = u64;
36 | type Call = Call;
37 | type BlockNumber = u64;
38 | type Hash = H256;
39 | type Hashing = BlakeTwo256;
40 | type AccountId = u64;
41 | type Lookup = IdentityLookup;
42 | type Header = Header;
43 | type Event = ();
44 | type BlockHashCount = BlockHashCount;
45 | type DbWeight = ();
46 | type Version = ();
47 | type PalletInfo = PalletInfo;
48 | type AccountData = ();
49 | type OnNewAccount = ();
50 | type OnKilledAccount = ();
51 | type SystemWeightInfo = ();
52 | type SS58Prefix = ();
53 | }
54 |
55 | impl Config for TestRuntime {
56 | type Event = ();
57 | }
58 |
59 | struct ExternalityBuilder;
60 |
61 | impl ExternalityBuilder {
62 | pub fn build() -> TestExternalities {
63 | let storage = system::GenesisConfig::default()
64 | .build_storage::()
65 | .unwrap();
66 | TestExternalities::from(storage)
67 | }
68 | }
69 |
70 | #[test]
71 | fn init_works() {
72 | ExternalityBuilder::build().execute_with(|| {
73 | assert_ok!(BasicToken::init(Origin::signed(1)));
74 | assert_eq!(BasicToken::get_balance(1), 21000000);
75 | })
76 | }
77 |
78 | #[test]
79 | fn cant_double_init() {
80 | ExternalityBuilder::build().execute_with(|| {
81 | assert_ok!(BasicToken::init(Origin::signed(1)));
82 | assert_noop!(
83 | BasicToken::init(Origin::signed(1)),
84 | Error::::AlreadyInitialized
85 | );
86 | })
87 | }
88 |
89 | #[test]
90 | fn transfer_works() {
91 | ExternalityBuilder::build().execute_with(|| {
92 | assert_ok!(BasicToken::init(Origin::signed(1)));
93 |
94 | // Transfer 100 tokens from user 1 to user 2
95 | assert_ok!(BasicToken::transfer(Origin::signed(1), 2, 100));
96 |
97 | assert_eq!(BasicToken::get_balance(1), 20999900);
98 | assert_eq!(BasicToken::get_balance(2), 100);
99 | })
100 | }
101 |
102 | #[test]
103 | fn cant_spend_more_than_you_have() {
104 | ExternalityBuilder::build().execute_with(|| {
105 | assert_ok!(BasicToken::init(Origin::signed(1)));
106 | assert_noop!(
107 | BasicToken::transfer(Origin::signed(1), 2, 21000001),
108 | Error::::InsufficientFunds
109 | );
110 | })
111 | }
112 |
--------------------------------------------------------------------------------
/pallets/basic-token/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/charity/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "charity"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A charitable organization that accepts donations and imbalances"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 | serde = '1.0'
13 |
14 | # Substrate packages
15 | pallet-balances = { version = '3.0', default-features = false }
16 | frame-support = { version = '3.0', default-features = false }
17 | frame-system = { version = '3.0', default-features = false }
18 | sp-runtime = { version = '3.0', default-features = false }
19 | sp-std = { version = '3.0', default-features = false }
20 |
21 | [dev-dependencies]
22 | sp-core = '3.0'
23 | sp-io = '3.0'
24 |
25 | [features]
26 | default = ['std']
27 | std = [
28 | 'pallet-balances/std',
29 | 'frame-support/std',
30 | 'frame-system/std',
31 | 'parity-scale-codec/std',
32 | 'sp-runtime/std',
33 | ]
34 |
--------------------------------------------------------------------------------
/pallets/charity/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/check-membership/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "check-membership"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A pallet that demonstrates permissioned method calls"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | frame-support = { version = '3.0', default-features = false }
14 | frame-system = { version = '3.0', default-features = false}
15 | sp-runtime = { version = '3.0', default-features = false }
16 | sp-std = { version = '3.0', default-features = false }
17 | account-set = { path = '../../traits/account-set', default-features = false }
18 | vec-set = { path = '../vec-set', default-features = false }
19 |
20 | [dev-dependencies]
21 | sp-core = '3.0'
22 | sp-io = '3.0'
23 | serde = '1.0'
24 |
25 | [features]
26 | default = ['std']
27 | std = [
28 | 'account-set/std',
29 | 'frame-support/std',
30 | 'frame-system/std',
31 | 'parity-scale-codec/std',
32 | 'sp-runtime/std',
33 | 'sp-std/std',
34 | 'vec-set/std',
35 | ]
36 |
--------------------------------------------------------------------------------
/pallets/check-membership/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(feature = "std"), no_std)]
2 |
3 | //! This module contains two nearly identical Substrate pallets. Both demonstrate access control
4 | //! and coupling multiple pallets together in a FRAME runtime.
5 | //!
6 | //! The _tight_ variant demonstrates tightly coupling pallets and is itself tightly coupled to the
7 | //! `vec-set` pallet.
8 | //!
9 | //! The _loose_ variant demonstrates loosely coupling pallets and is itself loosely coupled through
10 | //! the `AccountSet` trait.
11 |
12 | pub mod loose;
13 | pub mod tight;
14 |
--------------------------------------------------------------------------------
/pallets/check-membership/src/loose/mod.rs:
--------------------------------------------------------------------------------
1 | //! Pallet that demonstrates a minimal access control check. When a user calls this pallet's
2 | //! only dispatchable function, `check_membership`, the caller is checked against a set of approved
3 | //! callers. If the caller is a member of the set, the pallet's `IsAMember` event is emitted. Otherwise a `NotAMember` error is returned.
4 | //!
5 | //! The list of approved members is provided by an external source and exposed through an associated
6 | //! type in this pallet's configuration trait. Any type that implements the `AccountSet` trait can be
7 | //! used to supply the membership set.
8 |
9 | #![allow(clippy::unused_unit)]
10 | pub use pallet::*;
11 |
12 | #[cfg(test)]
13 | mod tests;
14 |
15 | #[frame_support::pallet]
16 | pub mod pallet {
17 | use account_set::AccountSet;
18 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
19 | use frame_system::pallet_prelude::*;
20 |
21 | /// The pallet's configuration trait
22 | /// Notice the loose coupling: any pallet that implements the `AccountSet` behavior works here.
23 | #[pallet::config]
24 | pub trait Config: frame_system::Config {
25 | /// The ubiquitous event type
26 | type Event: From> + IsType<::Event>;
27 |
28 | /// A type that will supply a set of members to check access control against
29 | type MembershipSource: AccountSet;
30 | }
31 |
32 | #[pallet::event]
33 | #[pallet::metadata(T::AccountId = "AccountId")]
34 | #[pallet::generate_deposit(pub (super) fn deposit_event)]
35 | pub enum Event {
36 | /// The caller is a member.
37 | IsAMember(T::AccountId),
38 | }
39 |
40 | #[pallet::error]
41 | pub enum Error {
42 | /// The caller is not a member
43 | NotAMember,
44 | }
45 |
46 | #[pallet::pallet]
47 | #[pallet::generate_store(pub (super) trait Store)]
48 | pub struct Pallet(PhantomData);
49 |
50 | #[pallet::hooks]
51 | impl Hooks> for Pallet {}
52 |
53 | #[pallet::call]
54 | impl Pallet {
55 | /// Checks whether the caller is a member of the set of account IDs provided by the
56 | /// MembershipSource type. Emits an event if they are, and errors if not.
57 | #[pallet::weight(10_000)]
58 | pub fn check_membership(origin: OriginFor) -> DispatchResultWithPostInfo {
59 | let caller = ensure_signed(origin)?;
60 |
61 | // Get the members from the `vec-set` pallet
62 | let members = T::MembershipSource::accounts();
63 |
64 | // Check whether the caller is a member
65 | ensure!(members.contains(&caller), Error::::NotAMember);
66 |
67 | // If the previous call didn't error, then the caller is a member, so emit the event
68 | Self::deposit_event(Event::IsAMember(caller));
69 | Ok(().into())
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/pallets/check-membership/src/loose/tests.rs:
--------------------------------------------------------------------------------
1 | use crate::loose::{self as check_membership, Config, Error};
2 | use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types};
3 | use sp_core::H256;
4 | use sp_io::TestExternalities;
5 | use sp_runtime::{
6 | testing::Header,
7 | traits::{BlakeTwo256, IdentityLookup},
8 | };
9 |
10 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
11 | type Block = frame_system::mocking::MockBlock;
12 |
13 | construct_runtime!(
14 | pub enum TestRuntime where
15 | Block = Block,
16 | NodeBlock = Block,
17 | UncheckedExtrinsic = UncheckedExtrinsic,
18 | {
19 | System: frame_system::{Module, Call, Config, Storage, Event},
20 | VecSet: vec_set::{Module, Call, Storage, Event},
21 | CheckMembership: check_membership::{Module, Call, Event},
22 | }
23 | );
24 |
25 | parameter_types! {
26 | pub const BlockHashCount: u64 = 250;
27 | pub BlockWeights: frame_system::limits::BlockWeights =
28 | frame_system::limits::BlockWeights::simple_max(1024);
29 | }
30 | impl frame_system::Config for TestRuntime {
31 | type BaseCallFilter = ();
32 | type BlockWeights = ();
33 | type BlockLength = ();
34 | type Origin = Origin;
35 | type Index = u64;
36 | type Call = Call;
37 | type BlockNumber = u64;
38 | type Hash = H256;
39 | type Hashing = BlakeTwo256;
40 | type AccountId = u64;
41 | type Lookup = IdentityLookup;
42 | type Header = Header;
43 | type Event = Event;
44 | type BlockHashCount = BlockHashCount;
45 | type DbWeight = ();
46 | type Version = ();
47 | type PalletInfo = PalletInfo;
48 | type AccountData = ();
49 | type OnNewAccount = ();
50 | type OnKilledAccount = ();
51 | type SystemWeightInfo = ();
52 | type SS58Prefix = ();
53 | }
54 |
55 | impl vec_set::Config for TestRuntime {
56 | type Event = Event;
57 | }
58 |
59 | impl Config for TestRuntime {
60 | type Event = Event;
61 | type MembershipSource = VecSet;
62 | }
63 |
64 | struct ExternalityBuilder;
65 |
66 | impl ExternalityBuilder {
67 | pub fn build() -> TestExternalities {
68 | let storage = frame_system::GenesisConfig::default()
69 | .build_storage::()
70 | .unwrap();
71 | let mut ext = TestExternalities::from(storage);
72 | ext.execute_with(|| System::set_block_number(1));
73 | ext
74 | }
75 | }
76 |
77 | #[test]
78 | fn members_can_call() {
79 | ExternalityBuilder::build().execute_with(|| {
80 | assert_ok!(VecSet::add_member(Origin::signed(1)));
81 |
82 | assert_ok!(CheckMembership::check_membership(Origin::signed(1)));
83 |
84 | let expected_event = Event::check_membership(check_membership::Event::IsAMember(1));
85 |
86 | assert_eq!(System::events()[1].event, expected_event,);
87 | })
88 | }
89 |
90 | #[test]
91 | fn non_members_cant_call() {
92 | ExternalityBuilder::build().execute_with(|| {
93 | assert_noop!(
94 | CheckMembership::check_membership(Origin::signed(1)),
95 | Error::::NotAMember
96 | );
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/pallets/check-membership/src/tight/mod.rs:
--------------------------------------------------------------------------------
1 | //! Pallet that demonstrates a minimal access control check. When a user calls this pallet's
2 | //! only dispatchable function, `check_membership`, the caller is checked against a set of approved
3 | //! callers. If the caller is a member of the set, the pallet's `IsAMember` event is emitted. Otherwise a `NotAMember` error is returned.
4 | //!
5 | //! The list of approved members is provided by the `vec-set` pallet. In order for this pallet to be
6 | //! used, the `vec-set` pallet must also be present in the runtime.
7 |
8 | #![allow(clippy::unused_unit)]
9 | pub use pallet::*;
10 |
11 | #[cfg(test)]
12 | mod tests;
13 |
14 | #[frame_support::pallet]
15 | pub mod pallet {
16 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
17 | use frame_system::pallet_prelude::*;
18 |
19 | /// The pallet's configuration trait.
20 | /// Notice the explicit tight coupling to the `vec-set` pallet
21 | #[pallet::config]
22 | pub trait Config: frame_system::Config + vec_set::Config {
23 | type Event: From> + IsType<::Event>;
24 | }
25 |
26 | #[pallet::event]
27 | #[pallet::metadata(T::AccountId = "AccountId")]
28 | #[pallet::generate_deposit(pub (super) fn deposit_event)]
29 | pub enum Event {
30 | /// The caller is a member.
31 | IsAMember(T::AccountId),
32 | }
33 |
34 | #[pallet::error]
35 | pub enum Error {
36 | /// The caller is not a member
37 | NotAMember,
38 | }
39 |
40 | #[pallet::pallet]
41 | #[pallet::generate_store(pub (super) trait Store)]
42 | pub struct Pallet(PhantomData);
43 |
44 | #[pallet::hooks]
45 | impl Hooks> for Pallet {}
46 |
47 | #[pallet::call]
48 | impl Pallet {
49 | /// Checks whether the caller is a member of the set of account IDs provided by the `vec-set`
50 | /// pallet. Emits an event if they are, and errors if not.
51 | #[pallet::weight(10_000)]
52 | pub fn check_membership(origin: OriginFor) -> DispatchResultWithPostInfo {
53 | let caller = ensure_signed(origin)?;
54 |
55 | // Get the members from the `vec-set` pallet
56 | let members = vec_set::Module::::members();
57 |
58 | // Check whether the caller is a member
59 | members
60 | .binary_search(&caller)
61 | .map_err(|_| Error::::NotAMember)?;
62 |
63 | // If the previous call didn't error, then the caller is a member, so emit the event
64 | Self::deposit_event(Event::IsAMember(caller));
65 | Ok(().into())
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/pallets/check-membership/src/tight/tests.rs:
--------------------------------------------------------------------------------
1 | use crate::tight::{self as check_membership, Config, Error};
2 | use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types};
3 | use sp_core::H256;
4 | use sp_io::TestExternalities;
5 | use sp_runtime::{
6 | testing::Header,
7 | traits::{BlakeTwo256, IdentityLookup},
8 | };
9 |
10 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
11 | type Block = frame_system::mocking::MockBlock;
12 |
13 | construct_runtime!(
14 | pub enum TestRuntime where
15 | Block = Block,
16 | NodeBlock = Block,
17 | UncheckedExtrinsic = UncheckedExtrinsic,
18 | {
19 | System: frame_system::{Module, Call, Config, Storage, Event},
20 | VecSet: vec_set::{Module, Call, Storage, Event},
21 | CheckMembership: check_membership::{Module, Call, Event},
22 | }
23 | );
24 |
25 | parameter_types! {
26 | pub const BlockHashCount: u64 = 250;
27 | pub BlockWeights: frame_system::limits::BlockWeights =
28 | frame_system::limits::BlockWeights::simple_max(1024);
29 | }
30 | impl frame_system::Config for TestRuntime {
31 | type BaseCallFilter = ();
32 | type BlockWeights = ();
33 | type BlockLength = ();
34 | type Origin = Origin;
35 | type Index = u64;
36 | type Call = Call;
37 | type BlockNumber = u64;
38 | type Hash = H256;
39 | type Hashing = BlakeTwo256;
40 | type AccountId = u64;
41 | type Lookup = IdentityLookup;
42 | type Header = Header;
43 | type Event = Event;
44 | type BlockHashCount = BlockHashCount;
45 | type DbWeight = ();
46 | type Version = ();
47 | type PalletInfo = PalletInfo;
48 | type AccountData = ();
49 | type OnNewAccount = ();
50 | type OnKilledAccount = ();
51 | type SystemWeightInfo = ();
52 | type SS58Prefix = ();
53 | }
54 |
55 | impl vec_set::Config for TestRuntime {
56 | type Event = Event;
57 | }
58 |
59 | impl Config for TestRuntime {
60 | type Event = Event;
61 | }
62 |
63 | struct ExternalityBuilder;
64 |
65 | impl ExternalityBuilder {
66 | pub fn build() -> TestExternalities {
67 | let storage = frame_system::GenesisConfig::default()
68 | .build_storage::()
69 | .unwrap();
70 | let mut ext = TestExternalities::from(storage);
71 | ext.execute_with(|| System::set_block_number(1));
72 | ext
73 | }
74 | }
75 |
76 | #[test]
77 | fn members_can_call() {
78 | ExternalityBuilder::build().execute_with(|| {
79 | assert_ok!(VecSet::add_member(Origin::signed(1)));
80 |
81 | assert_ok!(CheckMembership::check_membership(Origin::signed(1)));
82 |
83 | let expected_event = Event::check_membership(check_membership::Event::IsAMember(1));
84 |
85 | assert_eq!(System::events()[1].event, expected_event,);
86 | })
87 | }
88 |
89 | #[test]
90 | fn non_members_cant_call() {
91 | ExternalityBuilder::build().execute_with(|| {
92 | assert_noop!(
93 | CheckMembership::check_membership(Origin::signed(1)),
94 | Error::::NotAMember
95 | );
96 | })
97 | }
98 |
--------------------------------------------------------------------------------
/pallets/check-membership/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/compounding-interest/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "compounding-interest"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A savings account that uses fixed point arithmetic to implement compounding interest"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | substrate-fixed = { git = 'https://github.com/encointer/substrate-fixed.git', branch = "master" }
12 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
13 |
14 | # Substrate packages
15 | frame-support = { version = '3.0', default-features = false }
16 | frame-system = { version = '3.0', default-features = false }
17 | sp-arithmetic = { version = '3.0', default-features = false }
18 | sp-runtime = { version = '3.0', default-features = false }
19 | sp-std = { version = '3.0', default-features = false }
20 |
21 | [dev-dependencies]
22 | serde = '1.0'
23 |
24 | # Substrate packages
25 | sp-core = '3.0'
26 | sp-io = '3.0'
27 |
28 | [features]
29 | default = ['std']
30 | std = [
31 | 'frame-support/std',
32 | 'frame-system/std',
33 | 'parity-scale-codec/std',
34 | 'sp-arithmetic/std',
35 | 'sp-runtime/std',
36 | 'sp-std/std',
37 | ]
38 |
--------------------------------------------------------------------------------
/pallets/compounding-interest/types.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContinuousAccountData": {
3 | "principal": "u64",
4 | "deposit_date": "BlockNumber"
5 | },
6 | "U16F16": "[u8; 4]"
7 | }
8 |
--------------------------------------------------------------------------------
/pallets/constant-config/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "constant-config"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A pallet that demonstrates constants declared in the configuration trait"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 | sp-runtime = { version = '3.0', default-features = false }
17 |
18 | [dev-dependencies]
19 | serde = '1.0'
20 |
21 | # Substrate packages
22 | sp-core = '3.0'
23 | sp-io = '3.0'
24 |
25 | [features]
26 | default = ['std']
27 | std = [
28 | 'frame-support/std',
29 | 'frame-system/std',
30 | 'parity-scale-codec/std',
31 | 'sp-runtime/std',
32 | ]
33 |
--------------------------------------------------------------------------------
/pallets/constant-config/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(feature = "std"), no_std)]
2 | #![allow(clippy::unused_unit)]
3 | //! A pallet to demonstrate configurable pallet constants.
4 | //! This pallet has a single storage value that can be added to by calling the
5 | //! `add_value` extrinsic.
6 | //!
7 | //! The value added cannot exceed a maximum which is specified as a configuration constant.
8 | //! The stored value is cleared (set to zero) at a regular interval which is specified
9 | //! as a configuration constant.
10 |
11 | pub use pallet::*;
12 |
13 | #[cfg(test)]
14 | mod tests;
15 |
16 | #[frame_support::pallet]
17 | pub mod pallet {
18 | use frame_support::dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo};
19 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
20 | use frame_system::pallet_prelude::*;
21 | use sp_runtime::traits::Zero;
22 |
23 | #[pallet::config]
24 | pub trait Config: frame_system::Config {
25 | type Event: From + IsType<::Event>;
26 |
27 | /// Maximum amount added per invocation
28 | type MaxAddend: Get;
29 |
30 | /// Frequency with which the stored value is deleted
31 | type ClearFrequency: Get;
32 | }
33 |
34 | #[pallet::storage]
35 | #[pallet::getter(fn single_value)]
36 | pub(super) type SingleValue = StorageValue<_, u32, ValueQuery>;
37 |
38 | #[pallet::event]
39 | #[pallet::generate_deposit(pub(super) fn deposit_event)]
40 | pub enum Event {
41 | /// The value has ben added to. The parameters are
42 | /// ( initial amount, amount added, final amount)
43 | Added(u32, u32, u32),
44 | /// The value has been cleared. The parameter is the value before clearing.
45 | Cleared(u32),
46 | }
47 |
48 | #[pallet::pallet]
49 | #[pallet::generate_store(pub(super) trait Store)]
50 | pub struct Pallet(PhantomData);
51 |
52 | #[pallet::hooks]
53 | impl Hooks for Pallet {
54 | fn on_finalize(n: T::BlockNumber) {
55 | if (n % T::ClearFrequency::get()).is_zero() {
56 | let c_val = SingleValue::::get();
57 | SingleValue::::put(0u32);
58 | Self::deposit_event(Event::Cleared(c_val));
59 | }
60 | }
61 | }
62 |
63 | #[pallet::call]
64 | impl Pallet {
65 | /// Add to the stored value. The `val_to_add` parameter cannot exceed the specified manimum.
66 | #[pallet::weight(10_000)]
67 | pub fn add_value(origin: OriginFor, val_to_add: u32) -> DispatchResultWithPostInfo {
68 | let _ = ensure_signed(origin)?;
69 | ensure!(
70 | val_to_add <= T::MaxAddend::get(),
71 | "value must be <= maximum add amount constant"
72 | );
73 |
74 | // previous value got
75 | let c_val = SingleValue::::get();
76 |
77 | // checks for overflow when new value added
78 | let result = match c_val.checked_add(val_to_add) {
79 | Some(r) => r,
80 | None => {
81 | return Err(DispatchErrorWithPostInfo {
82 | post_info: PostDispatchInfo::from(()),
83 | error: DispatchError::Other("Addition overflowed"),
84 | })
85 | }
86 | };
87 | SingleValue::::put(result);
88 | Self::deposit_event(Event::Added(c_val, val_to_add, result));
89 | Ok(().into())
90 | }
91 |
92 | /// For testing purposes
93 | /// Sets the stored value to a given value
94 | #[pallet::weight(10_000)]
95 | pub fn set_value(origin: OriginFor, value: u32) -> DispatchResultWithPostInfo {
96 | let _ = ensure_signed(origin)?;
97 | SingleValue::::put(value);
98 | Ok(().into())
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/pallets/constant-config/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/currency-imbalances/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "currency-imbalances"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A pallet that demonstrates using currency imbalances"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 | sp-runtime = { version = '3.0', default-features = false }
17 |
18 | [dev-dependencies]
19 | sp-core = '3.0'
20 | sp-io = '3.0'
21 |
22 | [features]
23 | default = ['std']
24 | std = [
25 | 'frame-support/std',
26 | 'frame-system/std',
27 | 'parity-scale-codec/std',
28 | 'sp-runtime/std',
29 | ]
30 |
--------------------------------------------------------------------------------
/pallets/currency-imbalances/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(feature = "std"), no_std)]
2 | #![allow(clippy::unused_unit)]
3 | //! A Pallet to demonstrate using currency imbalances
4 | //!
5 | //! WARNING: never use this code in production (for demonstration/teaching purposes only)
6 | //! it only checks for signed extrinsics to enable arbitrary minting/slashing!!!
7 |
8 | use frame_support::{
9 | decl_event, decl_module,
10 | traits::{Currency, Imbalance, OnUnbalanced, ReservableCurrency},
11 | };
12 | use frame_system::ensure_signed;
13 |
14 | // balance type using reservable currency type
15 | type BalanceOf =
16 | <::Currency as Currency<::AccountId>>::Balance;
17 | type PositiveImbalanceOf = <::Currency as Currency<
18 | ::AccountId,
19 | >>::PositiveImbalance;
20 | type NegativeImbalanceOf = <::Currency as Currency<
21 | ::AccountId,
22 | >>::NegativeImbalance;
23 |
24 | pub trait Config: frame_system::Config + Sized {
25 | /// The overarching event type
26 | type Event: From> + Into<::Event>;
27 |
28 | /// Currency type for this pallet.
29 | type Currency: Currency + ReservableCurrency;
30 |
31 | /// Handler for the unbalanced increment when rewarding (minting rewards)
32 | type Reward: OnUnbalanced>;
33 |
34 | /// Handler for the unbalanced decrement when slashing (burning collateral)
35 | type Slash: OnUnbalanced>;
36 | }
37 |
38 | decl_event!(
39 | pub enum Event
40 | where
41 | AccountId = ::AccountId,
42 | Balance = BalanceOf,
43 | BlockNumber = ::BlockNumber,
44 | {
45 | SlashFunds(AccountId, Balance, BlockNumber),
46 | RewardFunds(AccountId, Balance, BlockNumber),
47 | }
48 | );
49 |
50 | decl_module! {
51 | pub struct Module for enum Call where origin: T::Origin {
52 | fn deposit_event() = default;
53 |
54 | /// Slashes the specified amount of funds from the specified account
55 | #[weight = 10_000]
56 | pub fn slash_funds(origin, to_punish: T::AccountId, collateral: BalanceOf) {
57 | let _ = ensure_signed(origin)?;
58 |
59 | let imbalance = T::Currency::slash_reserved(&to_punish, collateral).0;
60 | T::Slash::on_unbalanced(imbalance);
61 |
62 | let now = >::block_number();
63 | Self::deposit_event(RawEvent::SlashFunds(to_punish, collateral, now));
64 | }
65 |
66 | /// Awards the specified amount of funds to the specified account
67 | #[weight = 10_000]
68 | pub fn reward_funds(origin, to_reward: T::AccountId, reward: BalanceOf) {
69 | let _ = ensure_signed(origin)?;
70 |
71 | let mut total_imbalance = >::zero();
72 |
73 | let r = T::Currency::deposit_into_existing(&to_reward, reward).ok();
74 | total_imbalance.maybe_subsume(r);
75 | T::Reward::on_unbalanced(total_imbalance);
76 |
77 | let now = >::block_number();
78 | Self::deposit_event(RawEvent::RewardFunds(to_reward, reward, now));
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/pallets/currency-imbalances/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/default-instance/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "default-instance"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "An instantiable pallet featuring deafult instance"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 | sp-core = { version = '3.0', default-features = false }
17 | sp-runtime = { version = '3.0', default-features = false }
18 |
19 | [dev-dependencies]
20 | sp-io = '3.0'
21 |
22 | [features]
23 | default = ['std']
24 | std = [
25 | 'frame-support/std',
26 | 'frame-system/std',
27 | 'parity-scale-codec/std',
28 | 'sp-runtime/std',
29 | ]
30 |
--------------------------------------------------------------------------------
/pallets/default-instance/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! An example instantiable pallet (with default instance)
2 | //! TODO combine this and last caller into a singe crate (see check membership for an example)
3 |
4 | #![cfg_attr(not(feature = "std"), no_std)]
5 | #![allow(clippy::unused_unit)]
6 | pub use pallet::*;
7 |
8 | #[frame_support::pallet]
9 | pub mod pallet {
10 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
11 | use frame_system::pallet_prelude::*;
12 |
13 | // The pallet's configuration trait takes an instance as a type parameter. The instance type is
14 | // created by the `decl_storage!` macro below. Giving it a value of `DefaultInstance` allows us
15 | // to use the pallet in a runtime where only a single instance is desired without the extra syntax
16 | // that is otherwise needed to use instantiable pallets.
17 | #[pallet::config]
18 | pub trait Config: frame_system::Config {
19 | /// The overarching event type.
20 | type Event: From> + IsType<::Event>;
21 | }
22 |
23 | #[pallet::storage]
24 | pub(super) type Caller = StorageValue<_, T::AccountId, ValueQuery>;
25 |
26 | #[pallet::event]
27 | #[pallet::metadata(T::AccountId = "AccountId")]
28 | #[pallet::generate_deposit(pub (super) fn deposit_event)]
29 | pub enum Event {
30 | Called(T::AccountId),
31 | }
32 |
33 | #[pallet::pallet]
34 | #[pallet::generate_store(pub (super) trait Store)]
35 | pub struct Pallet(PhantomData);
36 |
37 | #[pallet::hooks]
38 | impl Hooks> for Pallet {}
39 |
40 | #[pallet::call]
41 | impl Pallet {
42 | /// The only dispatchable call, updates the single storage item,
43 | /// and emits an event.
44 | #[pallet::weight(10_000)]
45 | fn call(origin: OriginFor) -> DispatchResultWithPostInfo {
46 | let caller = ensure_signed(origin)?;
47 |
48 | // When writing to storage, we supply, not only a configuration T, but also an
49 | // instance, I.
50 | >::put(&caller);
51 | Self::deposit_event(Event::Called(caller));
52 | Ok(().into())
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/pallets/default-instance/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/double-map/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "double-map"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A pallet that demonstrates using a double map in Substrate"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 | sp-runtime = { version = '3.0', default-features = false }
17 | sp-std = { version = '3.0', default-features = false }
18 |
19 | [dev-dependencies]
20 | sp-core = '3.0'
21 | sp-io = '3.0'
22 | serde = '1.0'
23 |
24 | [features]
25 | default = ['std']
26 | std = [
27 | 'frame-support/std',
28 | 'frame-system/std',
29 | 'parity-scale-codec/std',
30 | 'sp-runtime/std',
31 | 'sp-std/std',
32 | ]
33 |
--------------------------------------------------------------------------------
/pallets/double-map/types.json:
--------------------------------------------------------------------------------
1 | {
2 | "GroupIndex": "u32"
3 | }
4 |
--------------------------------------------------------------------------------
/pallets/fixed-point/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "fixed-point"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | description = "A pallet that demonstrates using fixed-point arithmetic in Substrate"
7 | repository = "https://github.com/substrate-developer-hub/recipes"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 | substrate-fixed = { git = 'https://github.com/encointer/substrate-fixed.git', rev = "b33d186888c60f38adafcfc0ec3a21aab263aef1" }
13 |
14 | # Substrate packages
15 | frame-support = { version = '3.0', default-features = false }
16 | frame-system = { version = '3.0', default-features = false }
17 | sp-arithmetic = { version = '3.0', default-features = false }
18 | sp-core = { version = '3.0', default-features = false }
19 | sp-runtime = { version = '3.0', default-features = false }
20 | sp-std = { version = '3.0', default-features = false }
21 |
22 | [dev-dependencies]
23 | sp-io = '3.0'
24 | serde = '1.0'
25 |
26 | [features]
27 | default = ['std']
28 | std = [
29 | 'frame-support/std',
30 | 'frame-system/std',
31 | 'parity-scale-codec/std',
32 | 'sp-arithmetic/std',
33 | 'sp-runtime/std',
34 | 'sp-std/std',
35 | ]
36 |
--------------------------------------------------------------------------------
/pallets/fixed-point/types.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/pallets/generic-event/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "generic-event"
3 | version = "3.0.0"
4 | edition = "2018"
5 | authors = ['Substrate DevHub ']
6 | repository = 'https://github.com/substrate-developer-hub/recipes'
7 | description = "A pallet that raises events encapsulating data types from the configuration trait"
8 | license = "GPL-3.0-or-later"
9 |
10 | [dependencies]
11 | parity-scale-codec = { version = "2.0", features = ["derive"], default-features = false }
12 |
13 | # Substrate packages
14 | frame-support = { version = '3.0', default-features = false }
15 | frame-system = { version = '3.0', default-features = false }
16 | sp-runtime = { version = '3.0', default-features = false }
17 |
18 | [dev-dependencies]
19 | sp-core = '3.0'
20 | sp-io = '3.0'
21 | serde = '1.0'
22 |
23 | [features]
24 | default = ['std']
25 | std = [
26 | 'frame-support/std',
27 | 'frame-system/std',
28 | 'parity-scale-codec/std',
29 | 'sp-runtime/std',
30 | ]
31 |
--------------------------------------------------------------------------------
/pallets/generic-event/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Demonstration of Event variants that use type(s) from the pallet's configuration trait
2 |
3 | #![cfg_attr(not(feature = "std"), no_std)]
4 | #![allow(clippy::unused_unit)]
5 | pub use pallet::*;
6 |
7 | #[cfg(test)]
8 | mod tests;
9 |
10 | #[frame_support::pallet]
11 | pub mod pallet {
12 | use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
13 | use frame_system::pallet_prelude::*;
14 |
15 | #[pallet::pallet]
16 | #[pallet::generate_store(pub (super) trait Store)]
17 | pub struct Pallet(PhantomData);
18 |
19 | #[pallet::config]
20 | pub trait Config: frame_system::Config {
21 | /// The overarching event type.
22 | type Event: From> + IsType<::Event>;
23 | }
24 |
25 | #[pallet::hooks]
26 | impl Hooks> for Pallet {}
27 |
28 | #[pallet::event]
29 | #[pallet::metadata(T::AccountId = "AccountId")]
30 | #[pallet::generate_deposit(pub (super) fn deposit_event)]
31 | pub enum Event {
32 | /// Some input was sent
33 | EmitInput(T::AccountId, u32),
34 | }
35 |
36 | #[pallet::call]
37 | impl Pallet {
38 | /// A simple call that does little more than emit an event
39 | #[pallet::weight(10_000)]
40 | pub fn do_something(origin: OriginFor, input: u32) -> DispatchResultWithPostInfo {
41 | let user = ensure_signed(origin)?;
42 |
43 | // could do something with the input here instead
44 | let new_number = input;
45 |
46 | Self::deposit_event(Event::EmitInput(user, new_number));
47 | Ok(().into())
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/pallets/generic-event/src/tests.rs:
--------------------------------------------------------------------------------
1 | use crate::{self as generic_event, Config};
2 | use frame_support::{assert_ok, construct_runtime, parameter_types};
3 | use sp_core::H256;
4 | use sp_io::TestExternalities;
5 | use sp_runtime::{
6 | testing::Header,
7 | traits::{BlakeTwo256, IdentityLookup},
8 | };
9 |
10 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
11 | type Block = frame_system::mocking::MockBlock;
12 |
13 | construct_runtime!(
14 | pub enum TestRuntime where
15 | Block = Block,
16 | NodeBlock = Block,
17 | UncheckedExtrinsic = UncheckedExtrinsic,
18 | {
19 | System: frame_system::{Module, Call, Config, Storage, Event},
20 | GenericEvent: generic_event::{Module, Call, Event},
21 | }
22 | );
23 |
24 | parameter_types! {
25 | pub const BlockHashCount: u64 = 250;
26 | pub BlockWeights: frame_system::limits::BlockWeights =
27 | frame_system::limits::BlockWeights::simple_max(1024);
28 | }
29 | impl frame_system::Config for TestRuntime {
30 | type BaseCallFilter = ();
31 | type BlockWeights = ();
32 | type BlockLength = ();
33 | type Origin = Origin;
34 | type Index = u64;
35 | type Call = Call;
36 | type BlockNumber = u64;
37 | type Hash = H256;
38 | type Hashing = BlakeTwo256;
39 | type AccountId = u64;
40 | type Lookup = IdentityLookup;
41 | type Header = Header;
42 | type Event = Event;
43 | type BlockHashCount = BlockHashCount;
44 | type DbWeight = ();
45 | type Version = ();
46 | type PalletInfo = PalletInfo;
47 | type AccountData = ();
48 | type OnNewAccount = ();
49 | type OnKilledAccount = ();
50 | type SystemWeightInfo = ();
51 | type SS58Prefix = ();
52 | }
53 |
54 | impl Config for TestRuntime {
55 | type Event = Event;
56 | }
57 |
58 | struct ExternalityBuilder;
59 |
60 | impl ExternalityBuilder {
61 | pub fn build() -> TestExternalities {
62 | let storage = frame_system::GenesisConfig::default()
63 | .build_storage::