← Back to list

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
- Adding a Pallet to Runtime
- Runtime Migrations
- Runtime APIs
- Runtime Versioning
- Common Runtime Patterns
- Building and Testing
Runtime Structure
Three Runtime Variants
| Runtime | Chain ID | Network | Location |
|---|---|---|---|
| moonbase | 1287 | TestNet | runtime/moonbase/ |
| moonbeam | 1284 | Polkadot | runtime/moonbeam/ |
| moonriver | 1285 | Kusama | runtime/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:
- Add migration before release: Write the migration and register it
- Deploy: Migration runs once during the runtime upgrade
- 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:
MoonbaseMigrationsinruntime/moonbase/lib.rsMoonriverMigrationsinruntime/moonriver/lib.rsMoonbeamMigrationsinruntime/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 Type | Bump |
|---|---|
| Breaking storage change | spec_version |
| New pallet | spec_version |
| Runtime logic change | spec_version |
| Transaction format change | transaction_version |
| State version change | state_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