Skip to main content
Important: We do not provide financial advice or custody funds. All transactions occur on third-party platforms.

Common Patterns: Ownable, Pausable, Upgradeable Proxies

The patterns you'll see in every Solidity codebase. Access control, pause switches, the transparent and UUPS proxy models — when to use each and when each pattern goes wrong.

40 min · expert · part of Solidity & Smart Contract Development

The OpenZeppelin Library Is the De-Facto Standard

Before getting into specific patterns: most production Solidity codebases inherit from OpenZeppelin Contracts (https://github.com/OpenZeppelin/openzeppelin-contracts), the audited, battle-tested library that implements ERC-20, ERC-721, access control, pausability, upgradeable proxies, and most of the patterns covered in this lesson. You should generally not implement these from scratch. The library has had its own bugs over the years — none catastrophic in production code, but each one is documented in OZ's security advisories. The lesson is not "OZ is perfect"; the lesson is "rolling your own access control is rolling your own crypto." Use the library, pin the version (`forge install OpenZeppelin/openzeppelin-contracts@v5.0.1`), and stay current on advisories. OpenZeppelin maintains two parallel trees: `openzeppelin-contracts` (for normal contracts) and `openzeppelin-contracts-upgradeable` (for upgradeable proxies, where storage layout rules differ). Don't mix them — pick one based on whether you need upgradeability.

Also in this lesson

  • Ownable: Single-Owner Access Control
  • AccessControl: Role-Based Permissions
  • Pausable: The Kill Switch
  • Why Upgradeable Proxies Exist
  • Transparent Proxy (TUP)
  • UUPS Proxy and Storage Layout Rules

Key terms

OpenZeppelin Contracts
The audited, battle-tested standard library of Solidity patterns. Implements ERC standards, access control, pausability, upgradeable proxies. Default starting point for production contracts.
Ownable / Ownable2Step
Single-owner access control. Use Ownable2Step for production — the two-step transfer prevents the most expensive class of admin mistake.
AccessControl
Role-based access control. Each role is a `bytes32` constant; DEFAULT_ADMIN_ROLE can grant/revoke others. Separates duties so a compromised operational key has bounded blast radius.
Pausable
A modifier-based kill switch. `whenNotPaused` reverts state-changing calls during a pause. Trade-off: incident response capability vs. user trust in non-stoppability.
Proxy Pattern
A thin "proxy" contract holds storage and delegatecalls to a separate "implementation" contract for logic. The proxy address is the protocol's permanent identity; the implementation can be swapped to upgrade.
Transparent Upgradeable Proxy (TUP)
Proxy pattern where upgrade authorization lives on the proxy itself. Heavier per-call but safer — admin and user paths are routed separately.
UUPS Proxy
Proxy pattern where upgrade logic lives on the implementation. Cheaper per-call but you must include `_authorizeUpgrade` in every implementation, or you brick the proxy.
Storage Collision
A bug where a new implementation reorders, retypes, or deletes a state variable, so storage slots end up holding the wrong values. Catastrophic for upgradeable contracts. Prevent with strict layout discipline and the OZ Upgrades plugin.
Initializer / __gap
`initializer` is a modifier ensuring the init function can only run once. `__gap` is a reserved `uint256[N]` array between state variables, consumed as new variables are added — preserves layout across upgrades.

Continue this lesson — 6 more sections in the CryptoBipto app.

Open lesson

Educational only — not financial advice.