paritytech/substrate-skills/frame-pallet-guide
Claude Code and agent skill by paritytech/substrate-skills
- community
Checking that the SKILL.md file is still in the repository.
Provides FRAME pallet development best practices, patterns, and antipatterns for Substrate runtime development. Use when building new pallets, reviewing pallet code, or debugging pallet issues in the Individuality SDK or polkadot-sdk. Do not use for smart contract development, frontend code, or non-Substrate Rust projects. Guarantees correct pallet structure, safe arithmetic, bounded storage, and proper testing via curated reference from polkadot-sdk, PBA curriculum, and Individuality SDK patterns.
Install
npx vskill@latest install paritytech/substrate-skills/frame-pallet-guideSKILL.md
Frame Pallet Guide
1. Mode & Protocol
MODE: AUSTERE REFERENCE (Diataxis) ROLE: Substrate FRAME Pallet Development Expert CONSTRAINT: Thin FCIS shell. Load references per-intent only.
* PROCESS GATE — MANDATORY BEFORE ANY PALLET CHANGE * BEFORE writing pallet code: (1) Load relevant references. (2) Verify all storage uses bounded types + MaxEncodedLen. (3) Verify all arithmetic uses checked/saturating operations. (4) Verify all extrinsics have call_index + weight + origin check. * END PROCESS GATE *
2. Global Invariants
MUST enforce on every pallet creation or modification. NEVER skip.
| Invariant | Rule | |
|---|---|---|
| no_std | #![cfg_attr(not(feature = "std"), no_std)] header REQUIRED. All deps default-features = false. | |
| Bounded Storage | ALL storage MUST implement MaxEncodedLen. No unbounded Vec in production. | |
| Safe Arithmetic | NEVER raw +, -, *, / on balances. Use checked_* or saturating_*. | |
| No Panics | NEVER unwrap(), direct indexing, or division by zero in dispatchables. | |
| Determinism | NEVER HashMap, HashSet, f32, f64, OS randomness, or SystemTime. | |
| Call Index | EVERY extrinsic MUST have #[pallet::call_index(n)]. | |
| Origin Check | First line of every extrinsic MUST check origin. | |
| Events Last | Emit events AFTER all state mutations succeed. |
3. Decision Matrix
Locate matching row. Load ALL files in Artifacts column.
| User Intent | Action | Artifacts | |
|---|---|---|---|
| "Create new pallet" / scaffold pallet | Load structure + all references | references/pallet-structure.md, references/storage-and-types.md, references/calls-events-hooks.md, references/testing-patterns.md | |
| "Add storage" / storage design | Load storage reference | references/storage-and-types.md | |
| "Add extrinsic" / "add call" | Load calls reference | references/calls-events-hooks.md | |
| "Write tests" / "add tests" / mock setup | Load testing reference | references/testing-patterns.md | |
| "Add benchmarks" / weights | Load testing reference | references/testing-patterns.md | |
| "Review pallet" / check for issues | Load all references, check against invariants | references/pallet-structure.md, references/storage-and-types.md, references/calls-events-hooks.md | |
| Cargo.toml / dependencies / features | Load structure reference | references/pallet-structure.md | |
| Smart contract / non-Substrate code | STOP — Not applicable | — |
Execution Protocol
- Match intent to Decision Matrix row.
- Load all artifacts listed for that row.
- Apply patterns from loaded references.
- Verify against Global Invariants before finalizing.
4. Contrastive Exemplars
✅ CORRECT: Safe Storage + Arithmetic
| Phase | Content | |
|---|---|---|
| Trigger | "Add a vote tracking storage item" | |
| Action | StorageDoubleMap<_, Blake2_128Concat, RoundId, Blake2_128Concat, Alias, Ballot, OptionQuery> with BoundedVec for proposals, checked_mul for vote cost | |
| Result | Bounded, deterministic, safe from overflow |
❌ FAIL: Unbounded + Unsafe
| Phase | Content | |
|---|---|---|
| Trigger | "Add a vote tracking storage item" | |
| Action | StorageMap<_, Identity, AccountId, Vec<Vote>> with votes * votes for cost | |
| Result | Unbounded Vec (no MaxEncodedLen), Identity hasher on user key (DoS), raw multiplication (overflow) |
✅ CORRECT: Proper Extrinsic
| Phase | Content | |
|---|---|---|
| Trigger | "Add a vote extrinsic" | |
| Action | #[pallet::call_index(1)], #[pallet::weight(T::WeightInfo::vote())], let alias = T::EnsurePerson::ensure_origin(origin, &CTX)?; as first line, ensure! for validation, event last | |
| Result | Versioned, weighted, origin-checked, non-panicking |
❌ FAIL: Missing Guards
| Phase | Content | |
|---|---|---|
| Trigger | "Add a vote extrinsic" | |
| Action | No call_index, hardcoded weight, missing origin check, unwrap() on storage read | |
| Result | Breaking encoding changes, incorrect fees, anyone can call, runtime panic |
5. Anti-Patterns
| Pattern | Status | Reason | |
|---|---|---|---|
HashMap/HashSet in runtime | FORBIDDEN | Non-deterministic iteration breaks consensus | |
f32/f64 arithmetic | FORBIDDEN | Non-deterministic across platforms | |
unwrap()/expect() in dispatchables | FORBIDDEN | User-triggerable panic bypasses fees | |
vec[i] direct indexing | FORBIDDEN | Panic on out-of-bounds | |
Raw +/-/*// on balances | FORBIDDEN | Silent overflow/underflow | |
Unbounded Vec in storage | FORBIDDEN | No MaxEncodedLen, unprovable PoV | |
Identity hasher on user-controlled keys | FORBIDDEN | Storage key prediction enables DoS | |
Reading System::events() in production | FORBIDDEN | Inflates PoV size unboundedly | |
Unbounded iteration in on_initialize | FORBIDDEN | Block production DoS | |
Panic in on_initialize | FORBIDDEN | Halts block production (fatal for parachains) | |
Missing #[pallet::call_index] | FORBIDDEN | Extrinsic encoding breaks on reorder | |
| Tests at block 0 expecting events | FORBIDDEN | Events not recorded at genesis block | |
| Tight coupling when loose suffices | FORBIDDEN | Reduces reusability |
* RUNTIME CONTRACT — RECENCY ENFORCEMENT * BEFORE finalizing any pallet code, verify:
- ALL storage bounded with MaxEncodedLen?
- ALL arithmetic checked/saturating?
- ALL extrinsics have call_index + weight + origin check?
- NO panics possible (unwrap, indexing, division)?
- NO HashMap/HashSet/float/OS randomness?
IF any check fails → FIX before proceeding. * END RUNTIME CONTRACT *
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/frame-pallet-guide/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/paritytech/substrate-skills/frame-pallet-guide)