Back to list
manuelmauro

developing-runtime

by manuelmauro

A set of skill for Moonbeam developers

0🍴 0📅 Jan 20, 2026

SKILL.md


name: developing-runtime description: Develops and modifies the Moonbeam runtime using general patterns and best practices. Use when modifying runtime configuration, adding pallets to the runtime, implementing migrations, updating runtime APIs, or managing runtime versioning. license: MIT OR Apache-2.0

Runtime Development

Contents

Runtime Structure

Three Runtime Variants

RuntimeChain IDNetworkLocation
moonbase1287TestNetruntime/moonbase/
moonbeam1284Polkadotruntime/moonbeam/
moonriver1285Kusamaruntime/moonriver/

Key Files Per Runtime

runtime/moonbase/
├── lib.rs                    # Main runtime definition
├── precompiles.rs           # Precompile registry
├── xcm_config.rs            # XCM configuration
├── asset_config.rs          # Asset configuration
├── governance/              # Governance structs
├── weights/                 # Benchmark weights
├── migrations.rs            # Runtime migrations
└── runtime_params.rs        # Runtime parameters

Shared Code

runtime/common/src/
├── lib.rs                   # Common exports
├── apis.rs                  # Runtime API implementations
├── types.rs                 # Shared types
├── migrations.rs            # Common migrations
└── impl_*.rs               # Trait implementations

Adding a Pallet to Runtime

1. Add Dependency

# runtime/moonbase/Cargo.toml
[dependencies]
pallet-my-pallet = { workspace = true }

[features]
std = [
    # ...
    "pallet-my-pallet/std",
]
runtime-benchmarks = [
    # ...
    "pallet-my-pallet/runtime-benchmarks",
]
try-runtime = [
    # ...
    "pallet-my-pallet/try-runtime",
]

2. Configure the Pallet

// runtime/moonbase/lib.rs

// Parameter types
parameter_types! {
    pub const MyPalletParameter: u32 = 100;
}

// Implement Config
impl pallet_my_pallet::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type WeightInfo = pallet_my_pallet::weights::SubstrateWeight<Runtime>;
    type MyParameter = MyPalletParameter;
}

3. Add to construct_runtime!

// runtime/moonbase/lib.rs
construct_runtime!(
    pub enum Runtime {
        // System pallets
        System: frame_system = 0,
        // ...

        // Custom pallets (use unique indices)
        MyPallet: pallet_my_pallet = 100,
    }
);

4. Add Benchmarks (if applicable)

// runtime/moonbase/lib.rs
#[cfg(feature = "runtime-benchmarks")]
mod benches {
    frame_benchmarking::define_benchmarks!(
        // ...existing benchmarks
        [pallet_my_pallet, MyPallet]
    );
}

Runtime Migrations

Migration Lifecycle

Moonbeam follows a simple migration lifecycle:

  1. Add migration before release: Write the migration and register it
  2. Deploy: Migration runs once during the runtime upgrade
  3. Remove migration before next release: Delete the migration code

Migrations are one-shot: they run once and are removed from the codebase.

When Migrations Are Needed

  • Storage layout changes
  • Pallet index changes
  • Configuration changes that affect storage
  • Data transformations

Writing a Migration

// runtime/common/src/migrations.rs

/// Migration to update storage format.
/// Added in runtime XXXX, remove after deployment to all networks.
pub struct MigrateStorageFormat<T>(PhantomData<T>);

impl<T: pallet_my_pallet::Config> OnRuntimeUpgrade for MigrateStorageFormat<T> {
    fn on_runtime_upgrade() -> Weight {
        log::info!(target: "migration", "Running MigrateStorageFormat");

        let count = migrate_storage::<T>();

        log::info!(target: "migration", "Migrated {} items", count);
        T::DbWeight::get().reads_writes(count, count)
    }

    #[cfg(feature = "try-runtime")]
    fn pre_upgrade() -> Result<Vec<u8>, DispatchError> {
        let count = OldStorage::<T>::iter().count() as u32;
        Ok(count.encode())
    }

    #[cfg(feature = "try-runtime")]
    fn post_upgrade(state: Vec<u8>) -> Result<(), DispatchError> {
        let old_count: u32 = Decode::decode(&mut &state[..]).unwrap();
        let new_count = NewStorage::<T>::iter().count() as u32;
        ensure!(old_count == new_count, "Migration count mismatch");
        Ok(())
    }
}

Registering Migrations

// runtime/moonbase/lib.rs

/// Migrations to run on runtime upgrade.
/// Remove after deployment.
type MoonbaseMigrations = (
    migrations::MigrateStorageFormat<Runtime>,
);

pub type Executive = frame_executive::Executive<
    Runtime,
    Block,
    frame_system::ChainContext<Runtime>,
    Runtime,
    AllPalletsWithSystem,
    MoonbaseMigrations,
>;

Each runtime has its own migrations type:

  • MoonbaseMigrations in runtime/moonbase/lib.rs
  • MoonriverMigrations in runtime/moonriver/lib.rs
  • MoonbeamMigrations in runtime/moonbeam/lib.rs

After Deployment

Once migrations have run on all networks, clean up:

type MoonbaseMigrations = ();

Then remove the migration code from runtime/common/src/migrations.rs.

Runtime APIs

Implementing a Runtime API

// runtime/common/src/apis.rs
impl_runtime_apis! {
    impl my_pallet_runtime_api::MyPalletApi<Block> for Runtime {
        fn get_something() -> Option<u32> {
            pallet_my_pallet::Something::<Runtime>::get()
        }

        fn calculate_fee(amount: u128) -> u128 {
            // Computation that shouldn't be an extrinsic
            pallet_my_pallet::Pallet::<Runtime>::calculate_fee(amount)
        }
    }
}

Defining the API

// primitives/rpc/my-api/src/lib.rs
sp_api::decl_runtime_api! {
    pub trait MyPalletApi {
        fn get_something() -> Option<u32>;
        fn calculate_fee(amount: u128) -> u128;
    }
}

Runtime Versioning

When to Bump Versions

Change TypeBump
Breaking storage changespec_version
New palletspec_version
Runtime logic changespec_version
Transaction format changetransaction_version
State version changestate_version

Version Location

// runtime/moonbase/lib.rs
pub const VERSION: RuntimeVersion = RuntimeVersion {
    spec_name: create_runtime_str!("moonbase"),
    impl_name: create_runtime_str!("moonbase"),
    authoring_version: 4,
    spec_version: 3200,  // Bump for breaking changes
    impl_version: 0,
    apis: RUNTIME_API_VERSIONS,
    transaction_version: 2,
    state_version: 1,
};

Common Runtime Patterns

Configurable Origins

// Define custom origin
pub type EnsureRootOrHalfCouncil = EitherOfDiverse<
    EnsureRoot<AccountId>,
    pallet_collective::EnsureProportionAtLeast<AccountId, CouncilInstance, 1, 2>,
>;

impl pallet_my_pallet::Config for Runtime {
    type AdminOrigin = EnsureRootOrHalfCouncil;
}

Currency Configuration

impl pallet_my_pallet::Config for Runtime {
    type Currency = Balances;
    type MinimumDeposit = ConstU128<1_000_000_000_000>; // 1 GLMR
}

Event Filtering

// Filter events for specific pallets
impl frame_system::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    // Events from all pallets
}

Weight Configuration

impl pallet_my_pallet::Config for Runtime {
    // Use benchmarked weights
    type WeightInfo = pallet_my_pallet::weights::SubstrateWeight<Runtime>;

    // Or use placeholder for development
    // type WeightInfo = ();
}

Building and Testing

Build Runtime

# Build specific runtime
cargo build --release -p moonbase-runtime

# Build all runtimes
cargo build --release -p moonbeam-runtime -p moonriver-runtime -p moonbase-runtime

Test Runtime

# Run runtime tests
cargo test -p moonbase-runtime

# Test migrations with try-runtime
cargo build --release --features try-runtime
try-runtime --runtime target/release/wbuild/moonbase-runtime/moonbase_runtime.wasm \
    on-runtime-upgrade --checks all \
    live --uri wss://wss.api.moonbase.moonbeam.network

Generate Weights

# Run benchmarks for a pallet
./scripts/run-benches-for-runtime.sh moonbase release pallet_my_pallet

Checklist for Runtime Changes

  • Add pallet to all three runtimes (moonbase, moonbeam, moonriver)
  • Configure pallet parameters appropriately per network
  • Add to Cargo.toml with all feature flags
  • Add to construct_runtime! with unique index
  • Implement required Config traits
  • Add benchmarks and generate weights
  • Write migration if storage changes
  • Bump spec_version
  • Update runtime API if needed
  • Test with try-runtime
  • Run full test suite

Score

Total Score

55/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

0/5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon