[Blockchain Substrate Tutorials] Add a Pallet on Substrate Node Template

Pallet

The Substrate Node Template provides a minimal working runtime which you can use to quickly get started building your own custom blockchain. The Node Template includes a number of components, including a runtime that is constructed using FRAME runtime development framework. However, in order to remain minimal, it does not include most of the modules (called “pallets”) from Substrate’s set of core FRAME pallets.

This guide will show you how you can add the Nicks pallet. You can follow similar patterns to add additional FRAME pallets to your runtime, however you should note that each pallet is a little different in terms of the specific configuration settings needed to use it correctly. This tutorial will help you understand what you’ll need to consider when adding a new pallet to your FRAME runtime.

Install the Node Template

You should already have latest version of the Node Template compiled on your computer from when you completed the Create Your First Substrate Chain - https://substrate.dev/docs/en/tutorials/create-your-first-substrate-chain/ tutorial. If you do not, please complete it first.

Import the Nicks Pallet

We will now modify the Substrate Node Template to include the Nicks pallet. This pallet allows blockchain users to pay a deposit to reserve a nickname and associate it with an account they control.

Open the Node Template in your favorite code editor. We will be editing two files: runtime/src/lib.rs, and runtime/Cargo.toml.

Importing a Pallet Crate

The first thing you need to do to add the Nicks pallet is to import the pallet-nicks crate in your runtime’s Cargo.toml file. If you want a proper primer into Cargo References, please check out their official documentation.

Open substrate-node-template/runtime/Cargo.toml and you will see a list of all the dependencies your runtime has. For example, it depends on the Balances pallet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# runtime/Cargo.toml

# ...

[dependencies]
# ...

# Substrate dependencies
# ...
pallet-balances = { default-features = false, version = '3.0.0' }

pallet-nicks = { default-features = false, version = '3.0.0' }
# ...

Crate Features

One important thing we need to call out with importing pallet crates is making sure to set up the crate features correctly. In the code snippet above, you will notice that we set default-features = false. If you explore the Cargo.toml file even closer, you will find something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# runtime/Cargo.toml

# ...

[features]
default = ['std']

# ...

std = [
# ...
'pallet-balances/std',

'pallet-nicks/std',
# ...
]

# ...

This second line defines the default features of your runtime crate as std. You can imagine, each pallet crate has a similar configuration defining the default feature for the crate. Your feature will determine the features that should be used on downstream dependencies. For example, the snippet above should be read as:


The default feature for this Substrate runtime is std. When std feature is enabled for the runtime, codec, frame-executive, frame-support, and all the other listed dependencies should use their std feature.


This is important to enable the Substrate runtime to compile to both native binary, which supports Rust std, and Wasm binary, which do not (see: no_std).

Before moving on, check that the new dependencies resolve correctly by running:

1
$ cargo check -p node-template-runtime

Configure the Nicks Pallet

Every pallet has a component called Config that is used for configuration. This component is a Rust “trait”; traits in Rust are similar to interfaces in languages such as C++, Java and Go. FRAME developers must implement this trait for each pallet they would like to include in a runtime in order to configure that pallet with the parameters and types that it needs from the outer runtime. For instance, in the template pallet that is included in the Node Template, you will see the following Config configuration trait:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// runtime/src/lib.rs

impl pallet_balances::Config for Runtime {
// ...
}

/// Add this code block to your template for Nicks:
parameter_types! {
// Choose a fee that incentivizes desireable behavior.
pub const NickReservationFee: u128 = 100;
pub const MinNickLength: usize = 8;
// Maximum bounds on storage are important to secure your chain.
pub const MaxNickLength: usize = 32;
}

impl pallet_nicks::Config for Runtime {
// The Balances pallet implements the ReservableCurrency trait.
// `Balances` is defined in `construct_runtimes!` macro. See below.
// https://substrate.dev/rustdocs/latest/pallet_balances/index.html#implementations-2
type Currency = Balances;

// Use the NickReservationFee from the parameter_types block.
type ReservationFee = NickReservationFee;

// No action is taken when deposits are forfeited.
type Slashed = ();

// Configure the FRAME System Root origin as the Nick pallet admin.
// https://substrate.dev/rustdocs/latest/frame_system/enum.RawOrigin.html#variant.Root
type ForceOrigin = frame_system::EnsureRoot<AccountId>;

// Use the MinNickLength from the parameter_types block.
type MinLength = MinNickLength;

// Use the MaxNickLength from the parameter_types block.
type MaxLength = MaxNickLength;

// The ubiquitous event type.
type Event = Event;
}

Adding Nicks to the construct_runtime! Macro

Next, we need to add the Nicks pallet to the construct_runtime! macro. For this, we need to determine the types that the pallet exposes so that we can tell the runtime that they exist. The complete list of possible types can be found in the construct_runtime! macro documentation.

If we look at the Nicks pallet in detail, we know it has:

  • Module Storage: Because it uses the #[pallet::storage] macro.

  • Module Events: Because it uses the #[pallet::event] macro. You will notice that in the case of the Nicks pallet, the Event keyword is parameterized with respect to a type, T; this is because at least one of the events defined by the Nicks pallet depends on a type that is configured with the Config configuration trait.

  • Callable Functions: Because it has dispatchable functions in the #[pallet::call] macro.

  • The Pallet type from the #[pallet::pallet] macro.

Thus, when we add the pallet, it will look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// runtime/src/lib.rs

// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
// ...
Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},

/*** Add This Line ***/
Nicks: pallet_nicks::{Module, Call, Storage, Event<T>},

// ...
}
);

Interact with the Nicks Pallet

Now you are ready to compile and run your node that has been enhanced with nickname capabilities from the Nicks pallet. Compile the node in release mode with:

1
$ cargo build --release

After the build succeeds, you can start the node:

1
2
# Run a temporary node in development mode
$ ./target/release/node-template --dev --tmp

Start the Front-End

As in the previous tutorials, this tutorial will use the Substrate Developer Hub Front-End Template to allow you to interact with the Node Template. As long as you have completed the Create Your First Chain and Build a dApp tutorials, you should already be prepared to continue with the rest of this tutorial.

Refer directly to the front-end setup instructions for the Create Your First Chain Tutorial if necessary.

To start the Front-End Template, navigate to its directory and run:

1
$ yarn start

Use the Nicks Pallet

You should already be familiar with using the Front-End Template to interact with a pallet. In this section we will use the Nicks pallet to further illustrate how the Front-End Template can be used to interact with FRAME pallets. We will also learn more about how to use the Front-End Template to invoke privileged functions with the Sudo pallet, which is included by default as part of the Node Template. Finally, you will learn how to interpret the different types of events and errors that FRAME pallets may emit.

To get started, use the account selector from the Front-End Template to select Alice’s account and then use the Pallet Interactor component to call the setName dispatchable function from the nicks pallet. You can select any name you’d like as long as it is no shorter than the MinNickLength and no longer than the MaxNickLength you configured in the previous step. Use the Signed button to execute the function.

Use the Nicks Pallet

See Interact with the Nicks Pallet · Substrate Developer Hub - https://substrate.dev/docs/en/tutorials/add-a-pallet/interact-with-a-pallet to learn more about interacting with the Nicks Pallet

References

[1] Introduction · Substrate Developer Hub - https://substrate.dev/docs/en/tutorials/add-a-pallet/

[2] Installation · Substrate Developer Hub - https://substrate.dev/docs/en/knowledgebase/getting-started/

[3] Official Substrate Documentation for Blockchain Developers · Substrate Developer Hub - https://substrate.dev/

[4] substrate-developer-hub/substrate-node-template: A new FRAME-based Substrate node, ready for hacking. - https://github.com/substrate-developer-hub/substrate-node-template