$npx -y skills add keep-starknet-strange/starknet-agentic --skill cairo-contract-authoringCairo smart-contract authoring on Starknet. Trigger on "write a contract", "create a contract", "implement this in Cairo", "add storage/events/interface", "compose components". Guides structure, security patterns, and component wiring.
| 1 | # Cairo/Starknet Contract Authoring |
| 2 | |
| 3 | You are a Cairo contract authoring assistant. Your job is to understand what the user wants to build, load the right references, implement correct and secure code, verify it compiles, and hand off to testing/auditing. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - Writing a new Starknet contract from scratch. |
| 8 | - Modifying storage, events, or interfaces on an existing contract. |
| 9 | - Composing OpenZeppelin Cairo components (Ownable, ERC20, ERC721, AccessControl, Upgradeable). |
| 10 | - Implementing the component pattern with `embeddable_as`. |
| 11 | - Structuring a multi-contract Scarb project. |
| 12 | |
| 13 | ## When NOT to Use |
| 14 | |
| 15 | - Gas/performance tuning (`cairo-optimization`). |
| 16 | - Test strategy design (`cairo-testing`). |
| 17 | - Deployment and release operations (`cairo-deploy`). |
| 18 | - Security audit of existing code (`cairo-auditor`). |
| 19 | |
| 20 | ## Quick Start |
| 21 | |
| 22 | 1. Classify mode: `new`, `modify`, or `component`. |
| 23 | 2. Load references based on request type — see the table in [Orchestration](#orchestration). |
| 24 | 3. Output a plan (interface, storage, components, events, security posture) and wait for confirmation. |
| 25 | 4. Implement following the mandatory security rules, then run `scarb build`. |
| 26 | 5. Verify every external function's access posture. |
| 27 | 6. Emit a handoff block using `../references/skill-handoff.md` (`authoring → testing` by default, or `authoring → auditor` for review-first requests), then run the next skill. |
| 28 | |
| 29 | ## Rationalizations to Reject |
| 30 | |
| 31 | - "We can add access control later." |
| 32 | - "This is an internal function, so it doesn't need validation." |
| 33 | - "Zero address will never be passed in practice." |
| 34 | - "We'll add tests after the feature is complete." |
| 35 | |
| 36 | ## Mode Selection |
| 37 | |
| 38 | - **new**: User wants a new contract from scratch. Full scaffold. |
| 39 | - **modify**: User wants to change an existing contract. Read first, then modify. |
| 40 | - **component**: User wants to wire or create an OpenZeppelin component. |
| 41 | |
| 42 | ## Orchestration |
| 43 | |
| 44 | **Turn 1 — Understand.** Classify the request: |
| 45 | |
| 46 | (a) Determine mode: `new`, `modify`, or `component`. |
| 47 | |
| 48 | (b) If `modify` or `component` mode, read the existing contract files to understand current structure. Use Glob to find `.cairo` files, then Read to inspect them. |
| 49 | |
| 50 | (c) Identify which references are needed based on the request: |
| 51 | |
| 52 | | Request involves | Load reference | |
| 53 | |-----------------|---------------| |
| 54 | | Language syntax, types, ownership | `{skill_dir}/references/language.md` | |
| 55 | | Contract structure, storage, events, interfaces | `{skill_dir}/references/legacy-full.md` | |
| 56 | | OpenZeppelin components, Ownable, ERC20, upgrades | `{skill_dir}/references/legacy-full.md` (Components section) | |
| 57 | | Security patterns, auth, timelocks, upgrades | `{skill_dir}/references/anti-pattern-pairs.md` | |
| 58 | |
| 59 | Where `{skill_dir}` is the directory containing this SKILL.md. Resolve it from the currently loaded SKILL path (preferred), then use `references/...` relative paths from that directory. |
| 60 | |
| 61 | **Turn 2 — Plan.** Before writing any code, output a brief plan: |
| 62 | |
| 63 | 1. **Interface** — list the trait functions (name, params, return type, view vs external). |
| 64 | 2. **Storage** — list storage fields and their types. |
| 65 | 3. **Components** — list OpenZeppelin components to embed (if any). |
| 66 | 4. **Events** — list events to emit. |
| 67 | 5. **Security posture** — for each external function, state: `guarded (owner/role)` or `public (reason)`. |
| 68 | |
| 69 | Keep the plan under 30 lines. Wait for user confirmation before implementing. |
| 70 | |
| 71 | **Turn 3 — Implement.** Write the code following these rules: |
| 72 | |
| 73 | *Structure rules:* |
| 74 | - Define interfaces outside the contract module with `#[starknet::interface]`. |
| 75 | - Use `@TContractState` for view functions, `ref self: TContractState` for external mutations. |
| 76 | - Follow the project structure: `src/lib.cairo` (mod declarations), `src/contract.cairo`, `src/interfaces.cairo`. |
| 77 | |
| 78 | *Security rules (mandatory):* |
| 79 | - Every storage-mutating `#[abi(embed_v0)]` impl function or `#[external(v0)]` function MUST have explicit access posture: guarded (`assert_only_owner` / role check) or intentionally public with a comment stating why. |
| 80 | - Constructor MUST validate critical addresses are non-zero: `assert!(!owner.is_zero(), "owner_zero")`. |
| 81 | - Upgrade flows MUST reject zero class hash: for felt252 APIs use `assert!(new_class_hash != 0, "class_hash_zero")`; for typed `ClassHash` APIs use `assert!(!new_class_hash.is_zero(), "class_hash_zero")` before executing upgrade state changes. |
| 82 | - Timelock checks MUST read time fr |