Skip to main contentopenzeppelin
Expert usage of OpenZeppelin Contracts library for secure smart contract development. Covers access control, token standards, governance, upgrades, and security utilities.
Ir a la instalación Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/a5c-ai/babysitter --skill openzeppelinEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Ocupaciones relacionadasSOC
Basado en la clasificación ocupacional SOC
Reference for querying the Atlas knowledge graph through its MCP tools — the SECONDARY enrichment/comparison layer that adds best-practice context to systems you have ALREADY scanned from your real sources (`az`, repos, dirs). Use when you need to look up nodes, edges, kinds, clusters, stats, or wiki pages in Atlas to compare against your real inventory. (atlas graph, query atlas, atlas mcp, search the graph, graph neighbors, atlas record, atlas kinds, enrichment layer)
Atlas turns your STATED NEED into a real systems atlas by SCANNING your actual sources (Azure via `az`, git repos, local dirs) and process/data mining them, THEN enriching against the Atlas knowledge graph. Use this skill when asked to inventory/map your real systems, scan your cloud + repos + directories, mine the real processes or data they contain, or collect their real constraints/gotchas. (atlas, scan my systems, inventory our azure account, map my repos, real systems atlas, process mining, data mining, collect nuances, system discovery)
assimilate-popular-workflows This skill should be used when the user asks to "find skills in the wild", "assimilate popular workflows", "discover SKILL.md files in repos", "research external skills", "find workflow patterns", "survey the skill landscape", "what skills exist out there", or wants to investigate public repositories for extractable processes, babysitter plugins, and reusable procedural insights. Searches GitHub for SKILL.md files, classifies repos by archetype, and maintains structured research under docs/reference-repos/.
Explorador de archivos
2 archivos| name | openzeppelin |
| description | Expert usage of OpenZeppelin Contracts library for secure smart contract development. Covers access control, token standards, governance, upgrades, and security utilities. |
| allowed-tools | Read, Grep, Write, Bash, Edit, Glob, WebFetch |
| graph | {"domains":["domain:security"],"specializations":["specialization:cryptography-blockchain"],"skillAreas":["skill-area:smart-contract-development-testing","skill-area:authentication-authorization","skill-area:smart-contract-security"],"roles":["role:backend-engineer","role:security-engineer"]} |
OpenZeppelin Contracts Skill
Expert usage of OpenZeppelin Contracts, the standard library for secure smart contract development.
Capabilities
- Access Control: Ownable, AccessControl, Governor patterns
- Upgradeable Contracts: UUPS and Transparent Proxy plugins
- Token Standards: ERC-20, ERC-721, ERC-1155 implementations
- Security Utilities: ReentrancyGuard, Pausable, SafeERC20
- Governance: Governor and TimelockController
- Metatransactions: ERC-2771 support
- Cryptographic Utilities: ECDSA, MerkleProof, EIP712
Installation
npm install @openzeppelin/contracts
npm install @openzeppelin/contracts-upgradeable
npm install @openzeppelin/hardhat-upgrades
Access Control
Ownable
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyContract is Ownable {
constructor(address initialOwner) Ownable(initialOwner) {}
function protectedFunction() external onlyOwner {
// Only owner can call
}
}
AccessControl (Role-Based)
import "@openzeppelin/contracts/access/AccessControl.sol";
contract MyContract is AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
}
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
// Minting logic
}
function pause() external onlyRole(PAUSER_ROLE) {
// Pausing logic
}
}
AccessControlEnumerable
import "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol";
contract MyContract is AccessControlEnumerable {
function getAllAdmins() external view returns (address[] memory) {
uint256 count = getRoleMemberCount(DEFAULT_ADMIN_ROLE);
address[] memory admins = new address[](count);
for (uint256 i = 0; i < count; i++) {
admins[i] = getRoleMember(DEFAULT_ADMIN_ROLE, i);
}
return admins;
}
}
Token Standards
ERC-20 with Extensions
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract MyToken is ERC20, ERC20Burnable, ERC20Pausable, ERC20Permit, ERC20Votes, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
function pause() public onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() public onlyRole(PAUSER_ROLE) {
_unpause();
}
// Required overrides
function _update(address from, address to, uint256 value)
internal
override(ERC20, ERC20Pausable, ERC20Votes)
{
super._update(from, to, value);
}
function nonces(address owner)
public
view
override(ERC20Permit, Nonces)
returns (uint256)
{
return super.nonces(owner);
}
}
ERC-721 with Extensions
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
contract MyNFT is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Royalty {
uint256 private _tokenIdCounter;
constructor() ERC721("MyNFT", "MNFT") {
_setDefaultRoyalty(msg.sender, 500); // 5% royalty
}
function safeMint(address to, string memory uri) public {
uint256 tokenId = _tokenIdCounter++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// Required overrides
function _update(address to, uint256 tokenId, address auth)
internal
override(ERC721, ERC721Enumerable)
returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value)
internal
override(ERC721, ERC721Enumerable)
{
super._increaseBalance(account, value);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Royalty)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Governance
Governor Setup
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
contract MyGovernor is
Governor,
GovernorSettings,
GovernorCountingSimple,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorTimelockControl
{
constructor(
IVotes _token,
TimelockController _timelock
)
Governor("MyGovernor")
GovernorSettings(
1 days, // Voting delay
1 weeks, // Voting period
100e18 // Proposal threshold
)
GovernorVotes(_token)
GovernorVotesQuorumFraction(4) // 4% quorum
GovernorTimelockControl(_timelock)
{}
// Required overrides...
}
Upgradeable Contracts
UUPS Pattern
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyContractV1 is Initializable, UUPSUpgradeable, OwnableUpgradeable {
uint256 public value;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() public initializer {
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
}
function _authorizeUpgrade(address newImplementation)
internal
override
onlyOwner
{}
}
Deployment Script
const { ethers, upgrades } = require("hardhat");
async function main() {
const MyContract = await ethers.getContractFactory("MyContractV1");
const proxy = await upgrades.deployProxy(MyContract, [], {
initializer: "initialize",
kind: "uups",
});
await proxy.waitForDeployment();
console.log("Proxy:", await proxy.getAddress());
const MyContractV2 = await ethers.getContractFactory("MyContractV2");
await upgrades.upgradeProxy(await proxy.getAddress(), MyContractV2);
}
Security Utilities
SafeERC20
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract MyContract {
using SafeERC20 for IERC20;
function deposit(IERC20 token, uint256 amount) external {
token.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(IERC20 token, uint256 amount) external {
token.safeTransfer(msg.sender, amount);
}
}
ReentrancyGuard
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract MyContract is ReentrancyGuard {
function withdraw() external nonReentrant {
// Safe from reentrancy
}
}
MerkleProof
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract Airdrop {
bytes32 public merkleRoot;
function claim(bytes32[] calldata proof, uint256 amount) external {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount));
require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");
// Process claim
}
}
Process Integration
| Process | Purpose |
|---|
| All token processes | Token development |
governance-system.js | Governance |
smart-contract-upgrade.js | Upgrades |
staking-contract.js | Staking |
Best Practices
- Always use latest stable version
- Understand inheritance order
- Use Wizard for starting templates
- Audit custom extensions
- Test upgrade paths thoroughly
See Also