/SKILL.md
OpenZeppelin v5.x smart contract development rules for Solidity — access control, security patterns, ERC-20/721/1155 tokens, upgradeable proxies, gas optimization, testing with Foundry/Hardhat, and mainnet deployment best practices.
npx skillsauth add joaco2603/open-zepellin-skills openzeppelin-solidityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Apply these rules whenever writing, reviewing, or auditing Solidity smart contracts that use OpenZeppelin v5.x.
@openzeppelin/contracts (or @openzeppelin/contracts-upgradeable for upgradeable variants).import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"IERC20, IERC721) when only type information is needed.package.json or foundry.toml; never use "latest".SafeMath; rely on Solidity 0.8.x built-in overflow protection instead.Ownable requires passing initialOwner to the constructor; passing address(0) reverts._beforeTokenTransfer / _afterTokenTransfer with a single _update(to, tokenId, auth) hook.Ownable2Step (not Ownable) for any contract managing funds or critical parameters.AccessControl when multiple distinct roles are needed (MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE).bytes32 public constant ROLE_NAME = keccak256("ROLE_NAME")DEFAULT_ADMIN_ROLE to a multisig, never to an EOA in production.TimelockController; minimum delay: 24 h for params, 48 h for upgrades.onlyOwner and AccessControl in the same contract; choose one model.ReentrancyGuard and apply nonReentrant to every function that transfers ETH or calls external contracts.Pausable; restrict pause() to a PAUSER_ROLE, unpause() to DEFAULT_ADMIN_ROLE.unchecked {} only for loop counters where overflow is mathematically impossible.SafeCast.toUint128() instead of silent truncation.ECDSA.recover(hash, signature) and always hash with MessageHashUtils.toEthSignedMessageHash(hash).EIP712 base contract; never build domain separators manually.tx.origin for authentication; always use msg.sender.block.timestamp or blockhash as a source of randomness; use Chainlink VRF.address(0) before use.ERC20 or ERC20Burnable depending on whether supply needs to decrease.ERC20Permit for gasless approvals via off-chain signatures (EIP-2612).ERC20Votes when the token needs governance voting power tracking.ERC20Capped to enforce a hard maximum supply at contract level._transfer, store fee in basis points (feeBps / 10000), whitelist exempt addresses in a mapping._mint only in constructor or access-controlled minting functions, never in unrestricted public functions._safeMint (not _mint) to prevent tokens being locked in contracts that don't implement IERC721Receiver.ERC721URIStorage when each token needs an individual URI; use ERC721Enumerable only if on-chain enumeration is strictly required.uint256 _nextTokenId) for token IDs; never reuse them.ERC2981 for standard royalty info; use _setDefaultRoyalty in constructor.ERC1155Supply to track supply per token ID; batch mint with _mintBatch for airdrops.MerkleProof.verify for allowlist minting.uint128 + uint128 in one slot vs two separate slots.calldata instead of memory for external function parameters that are not modified.external instead of public when they are never called internally.++i instead of i++ in loops; use unchecked { ++i; } for counters that cannot overflow.uint256 len = arr.length.error Unauthorized(address caller)) instead of require strings — 50–70% gas saving on revert paths.immutable for values set in the constructor that never change (zero SLOAD cost).constant for compile-time known values (inlined, zero gas).indexed per event (EVM constraint).TokenMinted, RewardClaimed, RoleRevoked.@notice, @param, @return, @dev, and @custom:security-contact NatSpec to all public/external functions.keccak256).UUPSUpgradeable and override _authorizeUpgrade with onlyOwner or a governance check.initializer modifier from Initializable; call all __Parent_init() functions in order._disableInitializers() call in the logic contract constructor to prevent direct initialization.uint256[50] private __gap at the end of each upgradeable base contract.storageLayout diff with the OZ Upgrades Hardhat plugin before every upgrade.ProxyAdmin ownership to a multisig immediately after deployment.ERC4626 for yield-bearing vaults; override _decimalsOffset() to mitigate inflation attacks.updateReward(account) before any stake/unstake.require(answer > 0) and check updatedAt is within a staleness threshold.latestRoundData() (not latestAnswer()) to access timestamp and answeredInRound.Test from forge-std/Test.sol; name tests test_<Function>_<scenario>.vm.prank(address) for single-call impersonation; vm.startPrank/stopPrank for multi-call sequences.vm.expectRevert(CustomError.selector) before calls that should revert.vm.assume(condition) to filter inputs, bound(x, min, max) for realistic ranges.vm.rollFork(blockNumber) for deterministic CI tests.loadFixture to reset state between tests; expect(tx).to.emit(contract, "Event").withArgs(...) for events.invariant_ prefix) asserting system-wide properties (e.g., totalSupply == sum of balances).forge coverage --report lcov.deployments/<network>.json.slither and mythril static analysis on final bytecode before deployment.development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.