Skip to content

Latest commit

 

History

History
225 lines (137 loc) · 12.4 KB

File metadata and controls

225 lines (137 loc) · 12.4 KB

Where to go from here

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.

Bounties and tips

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.

Different governance models

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.

Sudo

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.

Council only (pallet-collective)

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.

Generation-1 (Council + Democracy)

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.

OpenGov + fellowship

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.

Honest summary

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.

Smart contracts

If users should deploy code without runtime upgrades.

pallet-revive (newer)

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.

pallet-contracts (legacy ink!)

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.

Frontier EVM

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-revive for new substrate-native contracts
  • pallet-contracts if you have existing ink! contracts to support
  • Frontier if Ethereum compatibility is your primary value proposition

Assets and NFTs

If the chain hosts user-defined fungible or non-fungible tokens.

pallet-assets

Multi-asset fungible tokens. Each asset has an ID, an owner, decimals, deposits for creation/storage. Used heavily by Polkadot Asset Hub.

pallet-nfts

Non-fungible tokens with collections, attributes, royalties, multiple instance types. Replaces the older pallet-uniques.

pallet-asset-conversion

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.

Recovery and vesting

Two adjacent account-layer pallets we skipped in lesson 6 and may be worth adding next:

pallet-recovery

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.

pallet-vesting

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.

Cross-chain — XCM and bridges

If the chain talks to other chains.

XCM

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.

Bridges

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.

Custom pallets

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 Config trait
  • 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.

Production hardening

What we've deliberately not covered:

Chain spec for production

  • Replace the dev/local presets with a staging and mainnet flow.
  • 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).

Validator operations

  • Key generation ceremony (use subkey or polkadot-launch tools; never reuse mnemonics).
  • Session-key rotation via author_rotateKeys against 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.

Tooling

  • 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).

Testing

  • Unit tests for custom pallets (mock runtime, pallet::tests).
  • Integration tests against the assembled runtime.
  • Try-runtime support (#[cfg(feature = "try-runtime")] impl in apis.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).

CI / DevOps

  • 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 full cargo build --release with the Wasm build.
  • A Docker image for validator deployment.
  • An RPC node image with a separate, slimmer configuration.
  • Automated chain-spec generation on tag.

Documentation

  • 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.

Security

  • 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).

How to pick the next step

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_registrar to 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.

Closing

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.


← Lesson 8 · Tutorial home