develop-secure-contrac…
Develop secure smart contracts using OpenZeppelin Contracts libraries. Use when users need to integrate OpenZeppelin library…
Upgrade Cairo smart contracts using OpenZeppelin's UpgradeableComponent on Starknet. Use when users need to: (1) make Cairo contracts upgradeable via replace_class_syscall, (2) integrate the OpenZeppelin UpgradeableComponent, (3) understand Starknet's class-based upgrade model
Claude Code
$ npx -y skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts --agent claude-code
Codex
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a codex -y
Cursor
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a cursor -y
Gemini CLI
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a gemini-cli -y
GitHub Copilot
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a github-copilot -y
OpenCode
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a opencode -y
Windsurf
$ npx skills add OpenZeppelin/openzeppelin-skills --skill upgrade-cairo-contracts -a windsurf -y
name: upgrade-cairo-contracts description: "Upgrade Cairo smart contracts using OpenZeppelin's UpgradeableComponent on Starknet. Use when users need to: (1) make Cairo contracts upgradeable via replace_class_syscall, (2) integrate the OpenZeppelin UpgradeableComponent, (3) understand Starknet's class-based upgrade model vs EVM proxy patterns, (4) ensure storage compatibility across upgrades, (5) guard upgrade functions with access control, or (6) test upgrade paths for Cairo contracts." license: AGPL-3.0-only metadata: author: OpenZeppelin
Starknet separates **contract instances** from **contract classes**. A class is the compiled program (identified by its class hash); a contract is a deployed instance pointing to a class. Multiple contracts can share the same class.
Upgrading a contract means **replacing its class hash** so it points to a new class. The contract keeps its address, storage, and nonce — only the code changes. This is fundamentally different from EVM proxy patterns:
| | Starknet | EVM (proxy pattern) | |---|---|---| | **Mechanism** | `replace_class_syscall` swaps the class hash in-place | Proxy `delegatecall`s to a separate implementation contract | | **Proxy contract needed** | No — the contract upgrades itself | Yes — a proxy sits in front of the implementation | | **Storage location** | Belongs to the contract directly | Lives in the proxy, accessed via delegatecall | | **Fallback routing** | Not applicable — no fallback/catch-all mechanism in Cairo | Proxy forwards all calls via fallback function |
The `replace_class_syscall` is a native Starknet syscall. When called, it atomically replaces the calling contract's class hash with the provided one. The new class must already be declared on-chain. After the syscall, the current execution frame continues with the old code, but subsequent calls to the contract — whether via `call_contract_syscall` later in the same transaction or in future transactions — execute the new code.
OpenZeppelin Contracts for Cairo provides an `UpgradeableComponent` that wraps `replace_class_syscall` with validation and event emission. Integrate it as follows:
1. **Declare the component** alongside an access control component (e.g., `OwnableComponent`) 2. **Add both to storage and events** using `#[substorage(v0)]` and `#[flat]` 3. **Expose an `upgrade` function** behind access control that calls the component's internal `upgrade` method — the component calls `replace_class_syscall` to atomically swap the class hash; always mention this syscall when explaining how Cairo upgrades work 4. **Initialize access control** in the constructor
The component emits an `Upgraded` event on each class hash replacement and rejects zero class hashes.
There is also an `IUpgradeAndCall` interface variant that couples the upgrade with a function call in the new class context — useful for post-upgrade migrations or re-initialization.
The `UpgradeableComponent` deliberately does **not** embed access control itself. You must guard the external `upgrade` function with your own check (e.g., `self.ownable.assert_only_owner()`). Forgetting this allows anyone to replace your contract's code.
Common access control options:
When replacing a class hash, existing storage is reinterpreted by the new class. Incompatible changes corrupt state:
Unlike Solidity's sequential storage layout, Cairo storage slots are derived from variable names via `sn_keccak` hashing (conceptually analogous to, but more fundamental than, ERC-7201 namespaced storage in Solidity). This makes ordering irrelevant but makes naming critical.
OpenZeppelin Contracts for Cairo follows semantic versioning for storage layout compatibility:
Before upgrading a production contract:
Agent skills for secure smart contract development with OpenZeppelin Contracts libraries and migration of Defender workflows.
Develop secure smart contracts using OpenZeppelin Contracts libraries. Use when users need to integrate OpenZeppelin library…
Migrate OpenZeppelin Defender Actions, Autotasks, Monitors and scheduled or Relayer-backed workflows to Chainlink CRE. Use when…
Review Sui Move code that integrates OpenZeppelin Contracts for Sui against the library's own patterns and conventions. Use this…
Set up a Cairo smart contract project with OpenZeppelin Contracts for Cairo on Starknet. Use when users need to: (1) create a new…
Set up a Solidity smart contract project with OpenZeppelin Contracts. Use when users need to: (1) create a new Hardhat or Foundry…
Set up a Stellar/Soroban smart contract project with OpenZeppelin Contracts for Stellar. Use when users need to: (1) install…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.