
Security / Audit·EVM
OpenZeppelin
Audited Solidity contract library (ERC-20/721/1155, AccessControl, upgradeable proxies, Governor) plus Defender for secure ops, deployments, monitoring, and Relayers. Contracts Wizard for code generation.
- 01production smart contract scaffolding
- 02upgradeable contracts (UUPS / Transparent / Beacon)
- 03role-based access control
- 04on-chain governance (Governor)
- 05secure deploys, monitoring, and incident response (Defender)
- pnpm add @openzeppelin/contracts
- pnpm add @openzeppelin/contracts-upgradeable
- pnpm add -D @openzeppelin/hardhat-upgrades
- pnpm add @openzeppelin/defender-sdk
| Variable | Scope | Description |
|---|---|---|
| DEFENDER_API_KEY | Server | OpenZeppelin Defender team API key. |
| DEFENDER_API_SECRET | Server | OpenZeppelin Defender API secret paired with the API key. |
Use OpenZeppelin Contracts as the base for all token, access-control, and governance code: `import "@openzeppelin/contracts/token/ERC20/ERC20.sol";` etc. Pin the version in `package.json` and never modify the library files. For upgradeable contracts use `@openzeppelin/contracts-upgradeable` plus `@openzeppelin/hardhat-upgrades` and call `await upgrades.deployProxy(Factory, args, { kind: 'uups' })`. For ops, instantiate the Defender SDK with `new Defender({ apiKey: DEFENDER_API_KEY, apiSecret: DEFENDER_API_SECRET })` to manage Relayers, Monitors, Actions, and Deploy. Generate boilerplate with the Contracts Wizard at wizard.openzeppelin.com when starting a new contract.
- ⚑UUPS vs Transparent proxies have very different trade-offs: UUPS is cheaper at runtime but the upgrade logic lives in YOUR implementation — forget `_authorizeUpgrade` and you brick upgrades. Transparent is safer but more gas. Pick one explicitly.
- ⚑Mixing `@openzeppelin/contracts` and `@openzeppelin/contracts-upgradeable` in the same contract corrupts storage layout; pick one set per contract and never inherit across the two.
- ⚑Storage gaps (`uint256[50] private __gap;`) are required in upgradeable parent contracts — adding state vars without preserving the gap shifts storage on upgrade and silently corrupts data.
- ⚑OpenZeppelin Defender is being sunset on July 1, 2026 — new projects should plan migration to OpenZeppelin Relayer + OpenZeppelin Monitor (open source) instead.
- ⚑`Ownable` is single-key by default; for production use `AccessControl` with a multisig admin or migrate to `Ownable2Step` to avoid accidental zero-address transfers.
- ⚑Always pin a specific version (e.g. `^5.1.0`) — minor versions occasionally introduce breaking interface changes (constructor arg order, role IDs).