Add Pallets to the Runtime¶
BeginnerIntroduction¶
In previous tutorials, you learned how to create a custom pallet and test it. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.
This tutorial will guide you through adding two pallets to your runtime: the custom pallet you previously developed and the utility pallet. This standard Polkadot SDK pallet provides powerful dispatch functionality. The utility pallet offers, for example, batch dispatch, a stateless operation that enables executing multiple calls in a single transaction.
Add the Pallets as Dependencies¶
First, you'll update the runtime's Cargo.toml
file to include the Utility pallet and your custom pallets as dependencies for the runtime. Follow these steps:
-
Open the
runtime/Cargo.toml
file and locate the[dependencies]
section. Add pallet-utility as one of the features for thepolkadot-sdk
dependency with the following line: -
In the same
[dependencies]
section, add the custom pallet that you built from scratch with the following line: -
In the
[features]
section, add the custom pallet to thestd
feature list: -
Save the changes and close the
Cargo.toml
file.Once you have saved your file, it should look like the following:
runtime/Cargo.toml
runtime/Cargo.toml[package] name = "parachain-template-runtime" description = "A parachain runtime template built with Substrate and Cumulus, part of Polkadot Sdk." version = "0.1.0" license = "Unlicense" authors.workspace = true homepage.workspace = true repository.workspace = true edition.workspace = true publish = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] docify = { workspace = true } substrate-wasm-builder = { optional = true, workspace = true, default-features = true } [dependencies] codec = { features = ["derive"], workspace = true } cumulus-pallet-parachain-system.workspace = true docify = { workspace = true } hex-literal = { optional = true, workspace = true, default-features = true } log = { workspace = true } pallet-parachain-template = { path = "../pallets/template", default-features = false } polkadot-sdk = { workspace = true, features = [ "pallet-utility", "cumulus-pallet-aura-ext", "cumulus-pallet-session-benchmarking", "cumulus-pallet-weight-reclaim", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-utility", "pallet-aura", "pallet-authorship", "pallet-balances", "pallet-collator-selection", "pallet-message-queue", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-xcm", "parachains-common", "polkadot-parachain-primitives", "polkadot-runtime-common", "runtime", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", ], default-features = false } scale-info = { features = ["derive"], workspace = true } serde_json = { workspace = true, default-features = false, features = [ "alloc", ] } smallvec = { workspace = true, default-features = true } custom-pallet = { path = "../pallets/custom-pallet", default-features = false } [features] default = ["std"] std = [ "codec/std", "cumulus-pallet-parachain-system/std", "log/std", "pallet-parachain-template/std", "polkadot-sdk/std", "scale-info/std", "serde_json/std", "substrate-wasm-builder", "custom-pallet/std", ] runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "hex-literal", "pallet-parachain-template/runtime-benchmarks", "polkadot-sdk/runtime-benchmarks", ] try-runtime = [ "cumulus-pallet-parachain-system/try-runtime", "pallet-parachain-template/try-runtime", "polkadot-sdk/try-runtime", ] # Enable the metadata hash generation. # # This is hidden behind a feature because it increases the compile time. # The wasm binary needs to be compiled twice, once to fetch the metadata, # generate the metadata hash and then a second time with the # `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` # extension. metadata-hash = ["substrate-wasm-builder/metadata-hash"] # A convenience feature for enabling things when doing a build # for an on-chain release. on-chain-release-build = ["metadata-hash"]
Update your root parachain template's Cargo.toml
file to include your custom pallet as a dependency. Follow these steps:
-
Open the
./Cargo.toml
file and locate the[workspace]
section.Make sure the
custom-pallet
is a member of the workspace:
./Cargo.toml
[workspace.package]
license = "MIT-0"
authors = ["Parity Technologies <admin@parity.io>"]
homepage = "https://paritytech.github.io/polkadot-sdk/"
repository = "https://github.com/paritytech/polkadot-sdk-parachain-template.git"
edition = "2021"
[workspace]
default-members = ["pallets/template", "runtime"]
members = [
"node", "pallets/custom-pallet",
"pallets/template",
"runtime",
]
resolver = "2"
[workspace.dependencies]
parachain-template-runtime = { path = "./runtime", default-features = false }
pallet-parachain-template = { path = "./pallets/template", default-features = false }
clap = { version = "4.5.13" }
color-print = { version = "0.3.4" }
docify = { version = "0.2.9" }
futures = { version = "0.3.31" }
jsonrpsee = { version = "0.24.3" }
log = { version = "0.4.22", default-features = false }
polkadot-sdk = { version = "2503.0.1", default-features = false }
prometheus-endpoint = { version = "0.17.2", default-features = false, package = "substrate-prometheus-endpoint" }
serde = { version = "1.0.214", default-features = false }
codec = { version = "3.7.4", default-features = false, package = "parity-scale-codec" }
cumulus-pallet-parachain-system = { version = "0.20.0", default-features = false }
hex-literal = { version = "0.4.1", default-features = false }
scale-info = { version = "2.11.6", default-features = false }
serde_json = { version = "1.0.132", default-features = false }
smallvec = { version = "1.11.0", default-features = false }
substrate-wasm-builder = { version = "26.0.1", default-features = false }
frame = { version = "0.9.1", default-features = false, package = "polkadot-sdk-frame" }
[profile.release]
opt-level = 3
panic = "unwind"
[profile.production]
codegen-units = 1
inherits = "release"
lto = true
Update the Runtime Configuration¶
Configure the pallets by implementing their Config
trait and update the runtime macro to include the new pallets:
-
Add the
OriginCaller
import: -
Implement the
Config
trait for both pallets at the end of theruntime/src/config/mod.rs
file:mod.rs... /// Configure the pallet template in pallets/template. impl pallet_parachain_template::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_parachain_template::weights::SubstrateWeight<Runtime>; } // Configure utility pallet. impl pallet_utility::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>; } // Define counter max value runtime constant. parameter_types! { pub const CounterMaxValue: u32 = 500; } // Configure custom pallet. impl custom_pallet::Config for Runtime { type RuntimeEvent = RuntimeEvent; type CounterMaxValue = CounterMaxValue; }
-
Locate the
#[frame_support::runtime]
macro in theruntime/src/lib.rs
file and add the pallets:
Recompile the Runtime¶
After adding and configuring your pallets in the runtime, the next step is to ensure everything is set up correctly. To do this, recompile the runtime with the following command (make sure you're in the project's root directory):
This command ensures the runtime compiles without errors, validates the pallet configurations, and prepares the build for subsequent testing or deployment.
Run Your Chain Locally¶
Launch your parachain locally and start producing blocks:
Tip
Generated chain TestNet specifications include development accounts "Alice" and "Bob." These accounts are pre-funded with native parachain currency, allowing you to sign and send TestNet transactions. Take a look at the Polkadot.js Accounts section to view the development accounts for your chain.
-
Create a new chain specification file with the updated runtime:
-
Start the omni node with the generated chain specification:
-
Verify you can interact with the new pallets using the Polkadot.js Apps interface. Navigate to the Extrinsics tab and check that you can see both pallets:
Where to Go Next¶
-
Tutorial Deploy on Paseo TestNet
Deploy your Polkadot SDK blockchain on Paseo! Follow this step-by-step guide for a seamless journey to a successful TestNet deployment.
-
Tutorial Pallet Benchmarking (Optional)
Discover how to measure extrinsic costs and assign precise weights to optimize your pallet for accurate fees and runtime performance.
| Created: December 17, 2024