Skip to content

Add an Existing Pallet to the Runtime

The Polkadot SDK Parachain Template provides a functional runtime that includes default FRAME development modules (pallets) to help you get started building a custom parachain. However, you'll often need to extend your runtime by adding additional pallets to enable new functionality.

Each pallet has specific configuration requirements, including the necessary parameters and types that enable its functionality. This guide walks you through the complete process of adding an existing pallet to your runtime and configuring it properly using pallet-utility as a practical example.

The Utility pallet offers batch transaction capabilities, enabling multiple calls to be dispatched together, as well as origin manipulation functionality for advanced use cases.

In this guide, you'll learn how to:

  • Update runtime dependencies to integrate a new pallet
  • Configure pallet-specific Rust traits to enable the pallet's functionality
  • Run your parachain locally to test the new pallet

Before you begin, ensure you have:

Add an Existing Polkadot SDK Pallet to Your Runtime

Section titled “Add an Existing Polkadot SDK Pallet to Your Runtime”

Adding a pallet to your parachain runtime involves configuring dependencies, implementing the pallet's configuration trait, and registering the pallet in the runtime construct.

The Polkadot SDK utilizes a monorepo structure, where multiple pallets are available as features of the polkadot-sdk dependency. A list of pallets can be found in the substrate/frame directory of the Polkadot SDK repository.

For pallet-utility, you need to add it as a dependency in the features array:

  1. Open the runtime/Cargo.toml file.

  2. Locate the [dependencies] section.

  3. Find the polkadot-sdk dependency.

  4. Add pallet-utility to the features array:

    polkadot-sdk = { workspace = true, features = [
    "pallet-utility",
    "cumulus-pallet-aura-ext",
    "cumulus-pallet-session-benchmarking",
    # ... other features
    ], default-features = false }

The Polkadot SDK runtime compiles to both a native binary (for running unit tests), which includes standard Rust library functions, and a WebAssembly (Wasm) binary (a more compact size for production use), which does not include the standard library. Since pallet-utility is part of the polkadot-sdk dependency, its std feature is already included when you enable polkadot-sdk/std.

To verify that the standard library features are enabled:

  1. In the runtime/Cargo.toml file, locate the [features] section.

  2. Ensure polkadot-sdk/std is included in the std array:

    [features]
    default = ["std"]
    std = [
    "codec/std",
    "cumulus-pallet-parachain-system/std",
    "log/std",
    "polkadot-sdk/std",
    "scale-info/std",
    # ... other features
    ]

Every pallet defines a Rust trait called Config that specifies the types and parameters needed for the pallet to function within a runtime. Before implementing the configuration, you should understand what the pallet requires.

The pallet-utility Config trait requires the following types:

pub trait Config: frame_system::Config {
/// The overarching event type
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The overarching call type
type RuntimeCall: Parameter
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
+ GetDispatchInfo
+ From<frame_system::Call<Self>>;
/// The caller origin, overarching type of all pallets origins
type PalletsOrigin: Parameter + Into<<Self as frame_system::Config>::RuntimeOrigin>;
/// Weight information for extrinsics in this pallet
type WeightInfo: WeightInfo;
}

This configuration requires:

  • RuntimeEvent: Links the pallet's events to the runtime's event system.
  • RuntimeCall: Allows the utility pallet to dispatch calls from other pallets, which is needed for batch operations.
  • PalletsOrigin: Enables origin manipulation for dispatching calls as other pallets.
  • WeightInfo: Provides weight calculations for pallet operations.

Now you'll implement the pallet's Config trait in your runtime to provide the concrete types the pallet needs.

To implement the Config trait:

  1. Open the runtime/src/configs/mod.rs file.

  2. Add the following implementation at the end of the file:

    /// Configure the utility pallet
    impl pallet_utility::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeCall = RuntimeCall;
    type PalletsOrigin = OriginCaller;
    type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
    }

The final step is to register the pallet in the runtime construct using the #[frame_support::runtime] macro. This macro generates the necessary boilerplate code for including pallets in the runtime.

To add the pallet to the runtime construct:

  1. Open the runtime/src/lib.rs file.

  2. Locate the #[frame_support::runtime] section (usually near the end of the file).

  3. Add your pallet with a unique pallet_index:

    #[frame_support::runtime]
    mod runtime {
    #[runtime::runtime]
    #[runtime::derive(
    RuntimeCall,
    RuntimeEvent,
    RuntimeError,
    RuntimeOrigin,
    RuntimeTask,
    RuntimeFreezeReason,
    RuntimeHoldReason,
    RuntimeSlashReason,
    RuntimeLockId,
    RuntimeViewFunction
    )]
    pub struct Runtime;
    #[runtime::pallet_index(0)]
    pub type System = frame_system;
    #[runtime::pallet_index(1)]
    pub type ParachainSystem = cumulus_pallet_parachain_system;
    #[runtime::pallet_index(2)]
    pub type Timestamp = pallet_timestamp;
    // ... other pallets
    #[runtime::pallet_index(50)]
    pub type Utility = pallet_utility;
    }

When adding the pallet:

  • Assign a unique pallet_index that doesn't conflict with existing pallets. The index determines the pallet's position in the runtime.
  • Use a descriptive name for the pallet instance, such as Utility for pallet_utility.

After adding and configuring your pallet in the runtime, verify that everything is set up correctly by compiling the runtime.

To compile the runtime:

  1. Navigate to the root directory of your project.

  2. Run the following command:

    Terminal window
    cargo build --release
  3. Ensure the build completes successfully without errors.

This command validates the pallet configurations and prepares the build for testing or deployment.

Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the Polkadot Omni Node. For instructions on setting up the Polkadot Omni Node and Polkadot Chain Spec Builder, refer to the Set Up a Parachain Template guide.

Create a new chain specification file with the updated runtime by running the following command from your project's root directory using the chain-spec-builder tool:

Terminal window
chain-spec-builder create -t development \
--relay-chain paseo \
--para-id 1000 \
--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \
named-preset development

This command generates a chain specification file, chain_spec.json, for your parachain with the updated runtime.

Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command:

Terminal window
polkadot-omni-node --chain ./chain_spec.json --dev

Verify the node starts successfully and begins producing blocks.

Use the Polkadot.js Apps interface to verify you can interact with the new pallet.

To interact with the pallet:

  1. Navigate to Polkadot.js Apps.

  2. Ensure you're connected to your local node at ws://127.0.0.1:9944.

  3. Go to the Developer > Extrinsics tab.

  4. In the submit the following extrinsic section, locate utility in the pallet dropdown.

  5. Verify you can see the available extrinsics, such as:

    • batch(calls): Dispatch multiple calls in a single transaction.
    • batchAll(calls): Dispatch multiple calls, stopping on the first error.
    • asDerivative(index, call): Dispatch a call as a derivative account.

You can now test the pallet's functionality by submitting transactions through the interface.

  • Add Multiple Pallet Instances


    Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime.

    → Get Started

  • Make a Custom Pallet


    Learn how to create custom pallets using FRAME.

    → Get Started

Last updated: