Reading time: ~10 min.
The tutorial ends at lesson 8 with a chain that produces blocks, finalizes them, has validators with real economic security, slashes misbehavior, governs itself via OpenGov, operates a treasury, supports identity / utility / multisig / proxy as the institutional-accounts layer, uses an H160-native account model (Ethereum-identical addresses and secp256k1 signatures), and runs a full Frontier EVM (so MetaMask can sign its EVM transactions) (pallet-evm + pallet-ethereum with the eth_* JSON-RPC surface). From here, the design tree branches into many directions — and the right next step depends entirely on what you want your chain to do.
This page surveys the branches we've discussed but not built. Each section is a roadmap, not a tutorial. Pick the one your chain needs and dive into the relevant substrate documentation, or open an issue and we'll add a real lesson.
pallet-treasury gives you spend (gated by SpendOrigin) and payout — that's it. Two adjacent pallets extend the model:
pallet-bounties— multi-stage paid work with a curator role. Propose → council/track approves and elects curator → curator pays out per-milestone. Designed for "we want $X work done, need oversight on whether it's done well." Polkadot uses bounties heavily.pallet-child-bounties— sub-bounties under a parent. Lets a curator delegate parts of a bounty without going back to governance for each sub-payment.pallet-tips— small-amount tipping by a fixed group of "tippers." Faster than a full referendum. Polkadot retired tips in 2023; Kusama still uses them.
Wiring them changes pallet_treasury::Config::SpendFunds from () to an aggregator type that lets each ancillary pallet participate in the spend cycle. Adds ~30–80 lines per pallet plus a track or two (SmallTipper, Tipper).
Pick when: you have actual treasury-spending workflows that benefit from a state machine more granular than "approve, pay" — e.g., milestone-gated work, frequent small tips.
Lesson 4 picked OpenGov. A different chain might pick differently. Short reference for each alternative; lesson 4's Other paths section has the detailed comparison.
pallet-sudo: a single key dispatches any root-origin extrinsic. ~5 lines of config. Centralised by construction, used by Polkadot at launch and removed via referendum two years later.
Pick when: dev / staging / foundation-controlled launch with a known sudo-removal plan.
A fixed-size committee voting by majority. No token-weighted voting. Multisig with on-chain audit trail. ~50 lines, plus a membership-management decision (static via pallet-membership or elected via pallet-elections-phragmen).
Pick when: consortium chains, federated infrastructure, foundation networks where a known group is trusted to govern.
pallet-collective + pallet-democracy + pallet-scheduler + pallet-preimage. Council proposes; token holders vote on referenda; scheduler enacts. ~150 lines, 4 pallets. Battle-tested but legacy — Polkadot moved past this to OpenGov in 2023.
Pick when: familiar UX is more important than modernity; your users already know Polkadot's Gen-1 model.
What we built plus pallet-whitelist + pallet-ranked-collective. The fellowship is a rank-based collective that can whitelist call hashes for fast-track dispatch. Adds substantial complexity for the benefit of an emergency-upgrade path that bypasses normal track thresholds.
Pick when: you have a clear technical body distinct from broader token holders, and emergency upgrades are likely enough to warrant the machinery.
If you're shipping a chain people will use, OpenGov is the destination. Gen-1 is the detour. Sudo is the stopgap. Council is the right pick when you genuinely want a federated, non-token-voted model.
If users should deploy code without runtime upgrades.
Polkadot's newer contracts pallet, designed for parallel execution and Ethereum-flavored semantics. EVM-style but compiled to PolkaVM, not the EVM bytecode VM. Smaller, faster, and the path forward in polkadot-sdk.
The original contracts pallet. Ink! contracts compile to Wasm and run in this pallet. Stable, widely used in existing chains (Astar, Aleph Zero, etc.). Being phased out in favor of pallet-revive.
Full Ethereum compatibility. Frontier ships pallets that emulate Ethereum's account model and EVM execution on Substrate. Pulls in significant complexity (RLP encoding, ECDSA signatures, EVM gas model) but lets existing Ethereum tools (MetaMask, Hardhat, web3.js) work unchanged.
When to pick which:
pallet-revivefor new substrate-native contractspallet-contractsif you have existing ink! contracts to support- Frontier if Ethereum compatibility is your primary value proposition
If the chain hosts user-defined fungible or non-fungible tokens.
Multi-asset fungible tokens. Each asset has an ID, an owner, decimals, deposits for creation/storage. Used heavily by Polkadot Asset Hub.
Non-fungible tokens with collections, attributes, royalties, multiple instance types. Replaces the older pallet-uniques.
A DEX pallet: swap between assets via constant-product AMM pools. Lets your chain host a built-in exchange.
Substantial pallets — pallet-assets is ~3000 lines, pallet-nfts similar. Add when fungible/NFT support is part of the chain's value proposition.
Two adjacent account-layer pallets we skipped in lesson 6 and may be worth adding next:
Social recovery. An account designates "friends" (other accounts) and a threshold; if the key is lost, the friends can collectively unlock recovery. Used historically as part of the Polkadot wallet-recovery flow. Skip if pallet-multisig already covers your key-compromise scenarios.
Time-locked balance transfers. Tokens unlock linearly between block A and block B. Useful for IDOs, vested grants, employee compensation schedules. About 50 lines of config plus a MAX_VESTING_SCHEDULES constant.
If the chain talks to other chains.
Cross-Consensus Messaging — the polkadot-sdk protocol for sending typed messages between chains. Used by parachains to talk to the relay chain and each other. For a solochain, XCM is useful only if you connect to the Polkadot/Kusama ecosystem (as a parachain) or implement XCM endpoints for custom routes.
Trustless bridges between chains. Polkadot has:
- BEEFY + Snowbridge — bridge to Ethereum and EVM chains
- Polkadot Bridge Hub — bridge between Polkadot and Kusama
For a solochain to bridge to Ethereum, you'd run a BEEFY-style light client of your own chain and verify finality proofs on Ethereum. Substantial work; consider only if cross-chain is a core feature.
The real reason most chains exist. Substrate gives you all the above as building blocks; the differentiator is your domain-specific logic.
A pallet typically has:
- A
Configtrait - Storage items (
#[pallet::storage]) - Extrinsics (
#[pallet::call]) - Events (
#[pallet::event]) - Errors (
#[pallet::error]) - Optional hooks (
on_initialize,on_finalize,on_runtime_upgrade)
Examples of custom-pallet shapes:
- A naming registry — accounts can claim names, names map to addresses, optional resale market.
- A reputation system — accounts accumulate reputation through specified actions.
- An oracle network — designated reporters submit data, runtime aggregates and exposes it.
- A subscription pallet — recurring payments between accounts.
- A custom auction — bidders, settlement, item delivery semantics.
- A messaging pallet — encrypted messages between accounts with on-chain delivery proofs.
Writing a pallet is its own substantial topic. The substrate-node-template tutorials walk through writing a pallet from scratch.
What we've deliberately not covered:
- Replace the dev/local presets with a
stagingandmainnetflow. - Mainnet typically uses a checked-in JSON chain spec, not a runtime preset.
- Bootnodes hardcoded in the chain spec.
- Telemetry endpoint configured.
- Real SS58 prefix (apply for one via the SS58 registry PR).
- Key generation ceremony (use
subkeyor polkadot-launch tools; never reuse mnemonics). - Session-key rotation via
author_rotateKeysagainst the validator's RPC. - Stash/controller key separation (cold storage of stash; warm controller).
- Monitoring (Prometheus + Grafana dashboards for slot inclusion, finality lag, peer count, missed blocks).
- High-availability node setups (active/passive failover).
- DDoS protection at the network layer.
- A block explorer (Subscan, custom Sidecar deployment, or polkadot.js apps).
- A JSON-RPC façade for stable client APIs.
- Indexers for application-level data.
- Wallet integration (signer/extension support).
- Unit tests for custom pallets (mock runtime,
pallet::tests). - Integration tests against the assembled runtime.
- Try-runtime support (
#[cfg(feature = "try-runtime")]impl inapis.rs) for safe runtime upgrades. - Benchmarks (
#[cfg(feature = "runtime-benchmarks")]) for production weights — not stubs. - Fuzz testing for extrinsic input handling.
- End-to-end tests (Zombienet, polkadot-launch, custom test harness).
- A GitLab/GitHub CI pipeline that runs
cargo fmt --check,cargo clippy --release --workspace --all-targets,cargo check --release --workspace --all-targets, and (for releases) the fullcargo build --releasewith the Wasm build. - A Docker image for validator deployment.
- An RPC node image with a separate, slimmer configuration.
- Automated chain-spec generation on tag.
- An operator's manual (how to run a validator, how to monitor it, what alerts mean).
- A user's manual (how to send tokens, stake, nominate, claim rewards).
- A developer's manual (extrinsic reference, RPC reference, custom pallet documentation).
- A runtime-upgrade runbook.
- Audit before mainnet launch.
- A responsible disclosure policy and bug bounty (treasury-funded — see lesson 5).
- Slashing-disabled period after launch (allow validators to find their footing before economic penalties bite).
Some questions that narrow the decision tree:
- "My chain needs governance different from what we built." → See Different governance models above. Lesson 4 chose OpenGov; sudo / council / Gen-1 are all viable alternatives for different chain shapes.
- "My chain needs money for ongoing development." → Already built in lesson 5; consider adding bounties/tips on top.
- "My chain needs accountable named actors." → Already built in lesson 6. First operational step is a GeneralAdmin referendum that calls
Identity::add_registrarto seat a registrar. - "My chain hosts smart contracts." → Pick
pallet-revive/pallet-contracts/ Frontier. - "My chain hosts user-defined tokens." →
pallet-assets,pallet-nfts. - "My chain talks to Ethereum." → Frontier or BEEFY+bridge.
- "My chain has a specific domain (gaming, identity, etc.)." → Write a custom pallet.
- "My chain needs to launch to mainnet." → Production hardening (chain spec, audits, ops, docs).
If you've reached the end of lesson 8 and don't have a clear answer to "what does my chain do?" — that's the first thing to decide. The technical work that follows is determined by the domain, not the other way around.
A solochain is plumbing. The interesting part of any chain is whatever's bolted on top of the plumbing. Lessons 1–8 got the plumbing solid — block production, finality, validator economics, on-chain governance, treasury, institutional accounts, H160 addressing, and a full Frontier EVM. What you build next determines whether the chain has reason to exist.
Good luck.