Create a new pallet
⚠️ This tutorial is out-of-date any may not work as intended. Please refer to
Polkadot SDK Docs
for up-to-date information.
In this workshop, you'll learn how to create a custom Substrate module-called a pallet-that's going to contain the code for your application-specific blockchain. Pallets are built using FRAME libraries and the Rust programming language. FRAME includes a lot of specialized macros that make it easy to compose the application logic in a reusable container. Let's get started by creating a new project and preparing a basic skeleton for the key parts of the Substrate collectibles application.
Create a new project
Because this workshop is all about demonstrating the full workflow for creating a new module—a new custom pallet—we won't start with the pallet-template
.
Instead, the first step is to create a new Rust package for the collectibles pallet you'll be building.
To create a project:
- Open a new terminal, if needed.
- Change to the
workshop-node-template/pallets
directory in your workspace. -
Create a new Rust project for the
collectibles
pallet by running the following command:cargo new collectibles
Note that
cargo
warns you that the new package isn't in the current workspace and there are a few different ways to fix the issue. For now, you can ignore the warning and continue preparing the new project. -
Change to the
collectibles
directory by running the following command:cd collectibles
-
View the contents of the
collectibles
directory and and notice that it provides a defaultCargo.toml
andsrc/main.rs
program:├── Cargo.toml └── src └── main.rs
In Rust, the
Cargo.toml
file for each package is called the package manifest and it defines configuration settings and dependencies that the package requires. TheCargo.toml
file in theworkspace-node-template/pallets/collectibles
folder defines the dependencies for thecollectibles
package you are building.By convention, the source code for Rust projects in Substrate—including pallet modules—is typically in the
src/lib.rs
file. By default, Cargo creates a templatesrc/main.rs
file for new projects. For clarity in the workshop, let's rename the main source file for the new module. -
Rename
src/main.rs
source file by running the following command:mv src/main.rs src/lib.rs
Now that your project files are in place, let's fix that issue that
cargo
warned you about by adding the new project to the current workspace.
Add the pallet to the workspace
As with other Rust programs, the node template has a Cargo.toml
manifest file.
In this case, the manifest file describes the workspace members.
To add the new pallet to the workspace:
- Change to the
workshop-node-template
directory in your workspace. - Open the
Cargo.toml
file in your code editor. -
Add the new
pallets/collectibles
pallet as a member of the workspace.[workspace] members = [ "node", "pallets/collectibles", "pallets/template", "runtime", ]
- Save your changes and close the file.
Prepare the project manifest
Your new project is now included in the workspace and ready for you to start configuring.
You already know that the project has a default Cargo.toml
manifest file and that this file describes the package attributes and dependencies.
Defining package attributes and dependencies is particularly important when developing a blockchain using Substrate and FRAME because the modular development environment enables you to import functionality from one part of code into another part of code and you can take advantage of this to reuse common functionality.
In this workshop, the collectibles
module is going to be part of the Substrate runtime and its Cargo.toml
file needs to define some modules it depends on.
For example, two core packages the collectibles
module requires are the frame_system
and frame_support
modules:
frame_system
provides core functionality for working with common data structures and primitives so they are available to all of the pallets that need them, enabling new pallets to be easily integrated into a runtime and to interact with each other.frame_support
provides core support services for handling function calls that are dispatched to the runtime, defining storage structures, preparing events and errors and core utilities.
In addition to frame_system
and frame_support
, the collectibles
module requires packages to support the type encoding and decoding required to minimize network traffic for the blockchain.
To support encoding and decoding in the SCALE format, the collectibles
module needs access to the codec
and scale-info
packages.
To update the manifest for the collectibles project:
- Open the default
Cargo.toml
file for thecollectibles
module in your code editor. -
Add
frame-support
andframe-system
to the dependencies.[dependencies] frame-support = { default-features = false, version = "36.0.0" } frame-system = { default-features = false, version = "36.0.0" }
-
Add
codec
andscale-info
to the dependencies.codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
-
Add the standard features for these packages to the
Cargo.toml
file to support the native binary target for the runtime.[features] default = ["std"] std = [ "frame-support/std", "frame-system/std", "codec/std", "scale-info/std", ]
Currently, the Substrate runtime is compiled to both a cross-platform WebAssembly target and platform-specific native binary target.
Prepare common code sections
You now have the bare minimum of package dependencies that your pallet requires specified in the Cargo.toml
manifest.
The next step is to prepare a set of common macros to serve as scaffolding for your new pallet.
-
Open
src/lib.rs
in a text editor and delete the templatemain()
function.You now have a clean slate for creating the Substrate collectibles pallet.
-
Prepare the scaffolding for the Substrate collectibles pallet by adding the following common set of marco declarations to the
src/lib.rs
file:#![cfg_attr(not(feature = "std"), no_std)] pub use pallet::*; #[frame_support::pallet(dev_mode)] pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; #[pallet::pallet] pub struct Pallet<T>(_); #[pallet::config] pub trait Config: frame_system::Config { } }
- Save your changes and close the file.
-
Verify that your program compiles by running the following command:
cargo build --package collectibles
You can ignore the compiler warnings about unused code for now.