Reference
Lookup material — pallets, rules, source pointers.
This page is the lookup surface. Tables, anchored entries, terse prose. If you arrived from an error message link elsewhere in the product, scroll straight to that anchor — you don't need to read the whole page.
Page audience: the developer extending a scaffolded project or debugging a failure. If you're a non-developer who landed here from a deep link, the entry you came for should give you what you need; the glossary at the bottom carries plain-English one-liners with links back out to the surfaces that own each term's introduction.
1. Pallet catalogue
Every pallet a shipped template wires, custom or SDK-supplied. The custom pallets are what ChainForge generates per-template; the SDK pallets come through the polkadot-sdk umbrella and the runtime template wires them automatically.
Custom pallets (one per template)
| Pallet | Template | Extrinsics |
|---|---|---|
| pallet_starter | generic | add_item, clear_items |
| pallet_governance | token-governance | endorse_hash, withdraw_endorsement, prune_account |
| pallet_prediction_market | prediction-market | create_market, place_bet, resolve_market |
| pallet_marketplace | marketplace | list_item, make_offer, accept_offer, cancel_listing |
SDK pallets templates wire
| Pallet | Where it's wired | Canonical source |
|---|---|---|
| pallet_balances | token-governance, prediction-market, marketplace | paritytech/polkadot-sdk/substrate/frame/balances |
| pallet_assets | marketplace | .../substrate/frame/assets |
| pallet_collective | token-governance | .../substrate/frame/collective |
| pallet_democracy | token-governance | .../substrate/frame/democracy |
| pallet_preimage, pallet_scheduler | token-governance (referenda machinery) | .../substrate/frame/preimage, /scheduler |
| pallet_timestamp | token-governance, prediction-market, marketplace | .../substrate/frame/timestamp |
Vitreus-canonical pallet repos are pending Foundation confirmation. Until they're fixed, the polkadot-sdk paths above are the reference points the templates link to and the CLAUDE.md fragments cite.
2. Validator rules (Vitreus-specific lints)
The Vitreus lint pass that catches chain-specific issues before testnet is not yet shipped. When it lands, this section will catalogue every rule it enforces — the pattern it matches, why it matters, and the fix template.
3. Footguns and recovery
The mistakes that bite real chains in production. Each entry has a stable anchor so failure cards and CLAUDE.md fragments can deep-link straight to the fix.
#weight-zero · Zero-weight dispatchable
Symptom: #[pallet::weight(0)] or #[pallet::weight(Weight::zero())] ships to a chain that charges fees. Every caller pays zero — a free DoS vector.
Root cause: The macro accepts the literal zero and compiles it through; no compile error, no warning. Looks like a placeholder but isn't.
Fix: Use #[pallet::weight(T::WeightInfo::<extrinsic>())] with a benchmarked WeightInfo impl. For developer iteration, the () placeholder impl in the shipped templates uses Weight::from_parts(15_000, 0) — non-zero, clearly placeholder, replaced before any fee-charging deployment.
#unbounded-vec · Unbounded Vec in storage
Symptom: StorageValue<_, Vec<u32>, ValueQuery>. An attacker fills the Vec until reads exceed the runtime weight budget; the chain stalls.
Fix: Use BoundedVec — bounded storage; the type carries its own cap, and the compiler refuses to let you forget to check the length:
StorageValue<_, BoundedVec<u32, T::MaxItems>, ValueQuery>
#missing-decode-with-mem-tracking · Missing DecodeWithMemTracking derive
Symptom: error[E0277]: the trait bound `<YourType>: DecodeWithMemTracking` is not satisfied on a custom enum or struct used in storage / events / extrinsic args.
Root cause: polkadot-sdk stable2603 requires every SCALE-decodable type used in dispatchable arguments or events to derive DecodeWithMemTracking alongside Decode. Not auto-implied, not in the prelude.
Fix: Add codec::DecodeWithMemTracking to the derive list:
#[derive(
Clone, PartialEq, Eq, Debug,
codec::Encode, codec::Decode, codec::DecodeWithMemTracking, codec::MaxEncodedLen,
scale_info::TypeInfo,
)]#missing-call-index · Missing call_index
Symptom: The FRAME macro refuses to expand without a #[pallet::call_index(N)] on every dispatchable.
Why it matters: Call indices are part of the API. Reordering or removing dispatchables without keeping indices stable breaks every signed extrinsic in flight on a live chain. Treat them like storage keys.
#mutate-instead-of-try-mutate · Using mutate where try_mutate is needed
Symptom: A storage closure that can fail uses Items::mutate instead of Items::try_mutate. The closure's Err gets swallowed; with BoundedVec::try_push the storage write panics on overflow.
Fix: try_mutate propagates the closure's error; the extrinsic returns it cleanly as a DispatchError.
#legacy-currency-reserve · Legacy Currency::reserve / transfer
Symptom: Code uses Currency::reserve or Currency::transfer on native balances. The trait family is deprecated; the future validator will flag.
Fix: Use the modern fungible::Mutate and fungible::MutateHold traits. The prediction-market template's place_bet extrinsic is the canonical example: stake held under a composite HoldReason::BetStake, released on resolution via NativeBalance::release.
#anonymous-extrinsic · Missing origin check
Symptom: A dispatchable mutates storage without calling ensure_signed or ensure_root (or a Config-trait origin guard). Anyone can fire it.
Fix: Always check origin. Default to let who = ensure_signed(origin)?; at the top of every dispatchable that writes. For root-only paths, ensure_root(origin)?. For seam-gated paths (oracle / multisig / council), an associated-type EnsureOrigin on Config — see the prediction-market template's ResolveOrigin.
4. Vitreus source pointers
When the CLAUDE.md fragments say “go read the canonical source,” this section is the map. By topic, with file paths.
Vitreus-canonical pallet repos are pending Foundation confirmation. Until they're published, the polkadot-sdk paths below are the working source of truth — Vitreus pallets follow the same conventions.
| Topic | Where to look |
|---|---|
| FRAME macros, pallet shape, traits | substrate/frame/support |
| Native token + holds | substrate/frame/balances |
| Multi-asset registry | substrate/frame/assets |
| Council / committee patterns | substrate/frame/collective |
| Referenda / public voting | substrate/frame/democracy |
| NFTs (marketplace swap-target) | substrate/frame/nfts |
| Timestamp (ambient) | substrate/frame/timestamp |
5. CLI reference
Commands the platform expects you to run locally. Flags that actually matter, not exhaustive option dumps.
Cargo (in your scaffold)
- cargo check
- Compile the project without producing a binary. Fastest way to confirm the code is well-formed. Run from the workspace root.
- cargo build --release --target wasm32-unknown-unknown
- Compile the runtime to a WASM blob. Run from
runtime/(or use-p chainforge-<template>-runtimefrom the workspace root). The resulting.wasmfile intarget/is what the relay chain stores and executes. - cargo test
- Run the unit tests. Most pallets in the shipped templates don't ship tests yet; this is forward-shaped scaffolding.
Substrate / polkadot-sdk tooling
- substrate build-spec --raw > chain-spec.raw.json
- Generate the raw chain spec from your project's
chain_spec.rs. Run inside a clone ofsubstrate-node-templatethat's been pointed at your runtime. - node-template --chain chain-spec.raw.json --base-path /tmp/<name>
- Launch a node against your chain spec. Add
--validator --alicefor dev-validator mode in a single-node setup.
6. Configuration knobs and version pins
The pins and constants the shipped templates carry. Tune the constants in your project's runtime/src/lib.rs parameter_types! block; the pins live in the workspace Cargo.toml.
Version pins (all templates)
- polkadot-sdk
2603.0.0(polkadot-stable2603 release line).- Rust toolchain
- channel
1.93, pinned viarust-toolchain.toml. - codec / scale-info
parity-scale-codec 3.6/scale-info 2.11.
Per-template constants (defaults)
These are the ConstU32 / ConstU128 values each runtime wires. The defaults are sane for dev; tune before any deployment that processes real volume.
| Template | Constant | Default |
|---|---|---|
| generic | MaxItems | 32 |
| token-governance | MaxProposalsPerAccount | 32 |
| prediction-market | MaxQuestionLen | 256 bytes |
| prediction-market | MaxBetsPerMarket | 32 |
| prediction-market | MinStake | 1_000 plancks |
| marketplace | MaxOffersPerListing | 64 |
| marketplace | MinPrice | 1_000 plancks |
7. Running the validator in CI
If you're wiring the validator into a CI pipeline — running it as a gate before pushes, in pull-request checks, or as a pre-commit hook — the existing /api/validate and /api/validate/git endpoints are the CI surface. No separate endpoint to script against, no special format flag. The JSON response is structured for both human reading and machine parsing.
The load-bearing field for a CI gate is summary.pass — true when no high-severity findings remain after filters apply, false otherwise. Wire pass to your job's exit code and you have a working gate.
7.1 — Worked example: paste mode
RESPONSE=$(curl -s -X POST https://chainforge.build/api/validate \
-H "Content-Type: application/json" \
-H "Cookie: chainforge_session=$CHAINFORGE_SESSION" \
-d "$(jq -n --arg src "$(cat pallets/pallet_starter/src/lib.rs)" '{source: $src}')")
PASS=$(echo "$RESPONSE" | jq -r '.summary.pass')
if [ "$PASS" = "true" ]; then
echo "✓ Validator passed"
exit 0
fi
echo "✗ Validator failed:"
echo "$RESPONSE" | jq -r '.findings[] | " [\(.severity)] \(.file):\(.line) \(.rule_id) — \(.reason)"'
exit 1The session cookie comes from a logged-in browser session today (extract via document.cookie in DevTools, paste into a CI secret). API-key auth for CI is a planned addition; the cookie approach is the current state.
7.2 — Worked example: git mode
RESPONSE=$(curl -s -X POST https://chainforge.build/api/validate/git \
-H "Content-Type: application/json" \
-H "Cookie: chainforge_session=$CHAINFORGE_SESSION" \
-d "$(jq -n --arg url "$GIT_URL" --arg ref "$GITHUB_SHA" '{git_url: $url, ref: $ref}')")
PASS=$(echo "$RESPONSE" | jq -r '.summary.pass')
[ "$PASS" = "true" ] || { echo "$RESPONSE" | jq '.findings'; exit 1; }$GITHUB_SHA is the canonical “validate this exact commit” pattern in GitHub Actions. Substitute the equivalent for other CI providers.
7.3 — Tuning the gate with filters
Two filter parameters let CI gates be specific about what they fail on:
rule_ids— allowlist of rule_id strings. Pass["unbounded_vec", "weight_zero"]to gate only on those two rules; everything else gets reported but doesn't fail the gate. Passing an empty list ([]) gates on nothing — all findings drop. Omit the field entirely to apply no rule filter.min_severity— severity floor."high"keeps only high-severity findings;"medium"keeps high + medium;"low"and"info"are progressively more permissive.
Both filters apply before summary.pass is computed, so the gate reflects the filtered view, not the unfiltered catalog.
When constructing bookmarkable filter URLs in the browser, use ?rules= (the URL form); when constructing API request bodies, use rule_ids (the API form). Same meaning, different field name.
Example — fail only on high-severity findings, ignore everything else:
curl -s -X POST https://chainforge.build/api/validate/git \
-H "Content-Type: application/json" \
-H "Cookie: chainforge_session=$CHAINFORGE_SESSION" \
-d '{"git_url": "https://github.com/owner/repo", "min_severity": "high"}' \
| jq '.summary.pass'7.4 — Exit codes
The validator endpoints return HTTP status codes, not exit codes — the CI script translates HTTP → exit. Typical patterns:
- HTTP 200 +
summary.pass == true→ exit 0 - HTTP 200 +
summary.pass == false→ exit 1 (gate fail) - HTTP 422 → exit 2 (request invalid: bad URL, bad ref, malformed filter params)
- HTTP 503 → exit 3 (validator infrastructure issue: clone failed, sandbox unavailable)
The detail field on non-200 responses carries a user-facing message safe to echo in CI logs.
8. Glossary
One-line definitions for every load-bearing term the four guides, the FAQ, the scaffold form, and the rendered CLAUDE.md introduce. Alphabetical. Each entry cross-links to the surface that owns the term's first-appearance layering, so if you want the full plain-English introduction you can follow the link out.
- BoundedVec
- Bounded storage; the type carries its own cap. The compiler refuses to let you forget to check the length. Use everywhere
Vecwould be tempting in storage. See footguns #unbounded-vec. - cargo / cargo check
- Rust's build tool;
cargo checkverifies a project compiles without producing a binary. First-introduced in getting started, step 4. - chain spec
- The configuration your chain starts with — who has tokens at block zero, what the chain calls itself, what network it joins. First-introduced in deploying §2.
- clone (verb)
- To make a working copy of a remote repository on your machine. Standard command is
git clone <url>. First-introduced in getting started, step 4. - collator
- The node software that runs your chain and submits its blocks to the relay chain. Different role from a validator — validators run the relay; collators run your chain. First laid out in deploying §4.
- dispatch error
- What a Substrate extrinsic returns when it fails. Each dispatch error has a module + index + name; the failure card maps them to plain-English copy.
- extrinsic
- A signed transaction in Substrate — the unit a user submits to change chain state. Signed by an account (so the chain knows who pays); the chain runs the dispatchable, which either succeeds or returns a dispatch error.
- genesis
- The formal name for “block zero” — the state the chain starts with. Configured by the chain spec. First-introduced in deploying §2.
- pallets
- The building blocks the scaffold generator wires up — each pallet provides a focused unit of chain behaviour (balances, governance, your custom logic). Composable via the runtime. First-introduced on the scaffold form helper.
- parachain
- A chain that lives inside a larger network (Vitreus, for ChainForge projects). The larger network handles security, finality, validator economics; your chain inherits the rest. First-introduced on the FAQ.
- polkadot.js apps
- The official browser UI for talking to any Substrate chain. What you use to sign extrinsics and watch blocks when there's no chain-specific UI yet. First-introduced in deploying §5.
- relay chain
- The Vitreus relay handles the heavy-duty pieces — security, finality, validator economics. Your parachain joins it as a tenant. First-introduced in deploying §4.
- runtime
- The state-transition logic of your chain. Compiles to a WASM blob the relay chain stores and executes. Upgradable without a redeploy. First-introduced in the rendered
CLAUDE.md+ the FAQ. - runtime upgrade
- Replacing the runtime WASM blob in storage via a single transaction. The chain switches to the new logic at the next block. Not a redeploy.
- signed extrinsic
- An extrinsic that carries a signature from an account — the chain knows who's paying for it. The standard form most user-facing actions take.
- Substrate parachain
- A parachain built on Substrate (the framework Vitreus uses). What ChainForge generates. First-introduced in the rendered
CLAUDE.md. - substrate-node-template
- The upstream Substrate project that ships a working node binary. The current-state manual path for running your scaffolded runtime: clone it, point its runtime dep at your project, build.
- testnet faucet
- A service that gives out test tokens for free. You need a small amount to sign the registration extrinsic when putting your chain on testnet. Vitreus testnet faucet URL pending Foundation confirmation.
- validator
- A node running the relay chain itself. Validators secure the relay; they don't run your chain (collators do that).
- WASM / WASM blob
- WebAssembly bytecode. Substrate runtimes compile to WASM so the relay chain can store and execute them. First- introduced in deploying §3.
- WeightInfo / Weight::from_parts
- The benchmarked weight estimate for a dispatchable; what tells the chain how much CPU/storage a call costs. The shipped templates use placeholder values; replace before any fee-charging deployment. See footguns #weight-zero.