Develop smart contracts using OpenZeppelin Contracts library. Use when the user wants to create or modify Solidity contracts that use OpenZeppelin — including token standards (ERC20, ERC721, ERC1155), access control (Ownable, AccessControl), security primitives (Pausable, ReentrancyGuard), or any OZ extension. Covers library-first integration, pattern discovery from installed source, and version-safe development.
Adapted from OpenZeppelin's official skill for Scaffold-ETH 2 Solidity projects.
Check if ./packages/nextjs/scaffold.config.ts exists directly in the current working directory (do not search subdirectories). If it doesn't exist, this is not a Scaffold-ETH 2 project. Follow the instructions at https://docs.scaffoldeth.io/SKILL.md to scaffold it first. If it exists, continue directly with building.
Detect the Solidity framework flavor:
packages/hardhat exists → Hardhat flavorpackages/foundry exists → Foundry flavorBefore writing ANY contract logic, search the installed OpenZeppelin library for an existing component:
virtualNever hand-write what the library already provides:
require(totalSupply() + amount <= cap) when ERC20Capped existsrequire(msg.sender == owner) when Ownable existsAPIs, override points, and import syntax change between major versions. Don't assume patterns from memory — always verify by reading the installed source.
Find the OpenZeppelin version and locate the installed source:
packages/hardhat/package.json for @openzeppelin/contracts version, then browse packages/hardhat/node_modules/@openzeppelin/contracts/packages/foundry/lib/openzeppelin-contracts/ and the remappings in packages/foundry/foundry.tomlBrowse the library's directory structure to discover available components. Key directories inside the OZ contracts root:
token/{ERC20,ERC721,ERC1155}/ — token standards and their base implementationstoken/{ERC20,ERC721}/extensions/ — Capped, Burnable, Pausable, Permit, Votes, Enumerable, etc.access/ — Ownable, AccessControl, AccessManagerutils/ — ReentrancyGuard, Pausable, math, structsLook at:
// ✅ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// ❌ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
virtual functions: only these can be overridden. Functions that were virtual in one version may not be in anotherNOTE: This function is not virtual, {X} should be overridden instead — follow theseFrom the source, identify only what's needed:
super)Integrate into existing code. Check for conflicts: duplicate access control, incompatible inheritance, missing overrides. The Solidity compiler will error if two parent contracts define the same function and you don't explicitly override it.
packages/hardhat/contracts/ (Hardhat) or packages/foundry/contracts/ (Foundry)packages/hardhat/deploy/ (Hardhat) or packages/foundry/script/ (Foundry)packages/nextjs/contracts/deployedContracts.ts (auto-generated by yarn deploy)