Secure Smart Contract library for Solidity with upgradeable implementations of standards like ERC20 and ERC721, flexible role-based permissioning schemes, and reusable components for building custom contracts and complex decentralized systems.
npx @tessl/cli install tessl/npm-openzeppelin--contracts-upgradeable@5.4.0OpenZeppelin Contracts Upgradeable is a secure smart contract library for Solidity that provides upgradeable implementations of standards like ERC20 and ERC721, flexible role-based permissioning schemes, and reusable components for building custom contracts and complex decentralized systems. All contracts follow the upgradeable pattern using ERC-7201 namespaced storage and initialization functions instead of constructors.
npm install @openzeppelin/contracts-upgradeable@openzeppelin/contracts (version 5.4.0)Standard import pattern for Solidity contracts:
import {ContractNameUpgradeable} from "@openzeppelin/contracts-upgradeable/module/ContractNameUpgradeable.sol";Common examples:
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";All upgradeable contracts follow this initialization pattern:
pragma solidity ^0.8.20;
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MyToken is Initializable, ERC20Upgradeable, OwnableUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner) initializer public {
__ERC20_init("MyToken", "MTK");
__Ownable_init(initialOwner);
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}OpenZeppelin Contracts Upgradeable is built around several key architectural patterns:
__ContractName_init() functions using the initializer modifierComprehensive permission management systems including role-based access control, ownership patterns, and advanced access management with time-based operations.
// Role-based access control
abstract contract AccessControlUpgradeable {
function hasRole(bytes32 role, address account) external view returns (bool);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
}
// Simple ownership pattern
abstract contract OwnableUpgradeable {
function owner() external view returns (address);
function transferOwnership(address newOwner) external;
modifier onlyOwner();
}Complete implementations of popular token standards including ERC-20 fungible tokens, ERC-721 NFTs, ERC-1155 multi-tokens, and the draft ERC-6909 standard.
// ERC-20 fungible tokens
contract ERC20Upgradeable {
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
}
// ERC-721 NFTs
contract ERC721Upgradeable {
function ownerOf(uint256 tokenId) external view returns (address);
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
}
// ERC-1155 multi-tokens
contract ERC1155Upgradeable {
function balanceOf(address account, uint256 id) external view returns (uint256);
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function setApprovalForAll(address operator, bool approved) external;
}Advanced DAO governance framework with flexible voting mechanisms, proposal management, timelock controllers, and vote delegation systems.
// Core governance contract
abstract contract GovernorUpgradeable {
function propose(address[] calldata targets, uint256[] calldata values, bytes[] calldata calldatas, string calldata description) external returns (uint256);
function castVote(uint256 proposalId, uint8 support) external returns (uint256);
function execute(address[] calldata targets, uint256[] calldata values, bytes[] calldata calldatas, bytes32 descriptionHash) external payable returns (uint256);
}
// Vote delegation and tracking
abstract contract VotesUpgradeable {
function getVotes(address account) external view returns (uint256);
function delegate(address delegatee) external;
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
}Essential security patterns including reentrancy guards, pausable functionality, multicall batching, and comprehensive cryptographic signature verification with modular signers supporting ECDSA, P256, RSA, and multi-signature schemes.
// Reentrancy protection
abstract contract ReentrancyGuardUpgradeable {
modifier nonReentrant();
}
// Emergency pause functionality
abstract contract PausableUpgradeable {
function paused() external view returns (bool);
modifier whenNotPaused();
modifier whenPaused();
}
// Batch multiple calls
abstract contract MulticallUpgradeable {
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}Core upgradeability infrastructure including the Initializable base contract and UUPS upgrade pattern for implementing upgradeable smart contracts.
// Initialization control
abstract contract Initializable {
modifier initializer();
modifier reinitializer(uint64 version);
modifier onlyInitializing();
}
// UUPS upgrade pattern
abstract contract UUPSUpgradeable {
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;
function proxiableUUID() external view returns (bytes32);
}Financial utilities including vesting wallets with linear and cliff-based release schedules for token distribution and payment management.
// Linear vesting wallet
contract VestingWalletUpgradeable {
function beneficiary() external view returns (address);
function start() external view returns (uint256);
function duration() external view returns (uint256);
function release() external;
function release(address token) external;
}ERC-2771 meta-transaction support enabling gasless transactions through trusted forwarders and context-aware message handling.
// Meta-transaction context
abstract contract ERC2771ContextUpgradeable {
function isTrustedForwarder(address forwarder) external view returns (bool);
function _msgSender() internal view returns (address);
}
// Meta-transaction forwarder
contract ERC2771ForwarderUpgradeable {
function verify(ForwardRequestData calldata request) external view returns (bool);
function execute(ForwardRequestData calldata request) external payable returns (bool, bytes memory);
}Draft ERC-7579 account abstraction implementations enabling modular smart contract accounts with validator, executor, and hook support.
// ERC-7579 account abstraction
abstract contract AccountERC7579Upgradeable {
function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external;
function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deinitData) external;
function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view returns (bool);
}// Common modifiers used across contracts
modifier initializer(); // Marks initialization functions
modifier onlyInitializing(); // Restricts to initialization phase
modifier reinitializer(uint64 version); // Marks re-initialization functions
// Storage pattern used by all contracts (ERC-7201)
bytes32 private constant StorageLocation = keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ContractName")) - 1)) & ~bytes32(uint256(0xff));
// Common events
event Initialized(uint64 version);All upgradeable contracts follow this standard pattern:
// Internal initialization functions
function __ContractName_init(/* parameters */) internal onlyInitializing {
__ContractName_init_unchained(/* parameters */);
}
function __ContractName_init_unchained(/* parameters */) internal onlyInitializing {
// Contract-specific initialization logic
}When inheriting multiple contracts, call all initializers in the correct order:
function initialize(/* parameters */) initializer public {
__ERC20_init("TokenName", "TKN");
__Ownable_init(initialOwner);
__CustomContract_init(/* custom parameters */);
}