Secure Smart Contract library providing battle-tested implementations of industry-standard Solidity contracts including ERC20, ERC721, ERC1155 tokens, access control mechanisms, proxy patterns, and governance systems for Ethereum and EVM-compatible blockchains.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
OpenZeppelin Contracts provides comprehensive proxy patterns for creating upgradeable and flexible smart contract systems. These patterns enable contract upgradeability, gas-efficient contract cloning, and sophisticated deployment strategies.
Import proxy contracts using Solidity import statements:
import "@openzeppelin/contracts/proxy/Clones.sol";
import "@openzeppelin/contracts/proxy/Proxy.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";Gas-efficient cloning of contracts using minimal proxy pattern. Creates lightweight proxy contracts that delegate all calls to a single implementation.
library Clones {
function clone(address implementation) internal returns (address instance);
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance);
function predictDeterministicAddress(address implementation, bytes32 salt, address deployer) internal pure returns (address predicted);
function predictDeterministicAddress(address implementation, bytes32 salt) internal pure returns (address predicted);
}pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/Clones.sol";
contract TokenFactory {
address public immutable tokenImplementation;
constructor(address _tokenImplementation) {
tokenImplementation = _tokenImplementation;
}
function createToken(string memory name, string memory symbol) external returns (address) {
bytes32 salt = keccak256(abi.encodePacked(name, symbol, msg.sender));
address tokenClone = Clones.cloneDeterministic(tokenImplementation, salt);
// Initialize the cloned token
IToken(tokenClone).initialize(name, symbol, msg.sender);
return tokenClone;
}
function predictTokenAddress(string memory name, string memory symbol) external view returns (address) {
bytes32 salt = keccak256(abi.encodePacked(name, symbol, msg.sender));
return Clones.predictDeterministicAddress(tokenImplementation, salt);
}
}Base proxy contract providing the foundation for all proxy patterns through delegate call functionality.
abstract contract Proxy {
function _delegate(address implementation) internal virtual;
function _implementation() internal view virtual returns (address);
function _fallback() internal virtual;
function _beforeFallback() internal virtual;
}Standard for upgradeable proxies with standardized storage slots for implementation addresses.
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
constructor(address _logic, bytes memory _data);
}
abstract contract ERC1967Upgrade {
function _getImplementation() internal view returns (address);
function _setImplementation(address newImplementation) internal;
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal;
function _getAdmin() internal view returns (address);
function _setAdmin(address newAdmin) internal;
function _changeAdmin(address newAdmin) internal;
function _getBeacon() internal view returns (address);
function _setBeacon(address newBeacon) internal;
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal;
}Transparent proxy pattern that separates admin and user functions to avoid function selector clashes.
contract TransparentUpgradeableProxy is ERC1967Proxy {
constructor(address _logic, address admin_, bytes memory _data);
}
contract ProxyAdmin is Ownable {
function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address);
function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address);
function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner;
function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner;
function upgradeAndCall(ITransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual onlyOwner;
}pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
contract MyContractV1 is Initializable {
uint256 public value;
function initialize(uint256 _value) public initializer {
value = _value;
}
function setValue(uint256 _value) public {
value = _value;
}
}
// Deploy script would create:
// 1. Implementation: MyContractV1
// 2. ProxyAdmin: ProxyAdmin
// 3. Proxy: TransparentUpgradeableProxy(implementation, admin, initData)User Upgradeable Proxy Standard where upgrade logic is in the implementation contract rather than the proxy.
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
modifier onlyProxy();
modifier notDelegated();
function proxiableUUID() external view virtual override notDelegated returns (bytes32);
function upgradeTo(address newImplementation) external virtual onlyProxy;
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable virtual onlyProxy;
function _authorizeUpgrade(address newImplementation) internal virtual;
}pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyUUPSContract is UUPSUpgradeable, OwnableUpgradeable {
uint256 public value;
function initialize(uint256 _value) public initializer {
__Ownable_init();
__UUPSUpgradeable_init();
value = _value;
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function setValue(uint256 _value) public {
value = _value;
}
}Proxy pattern where multiple proxies delegate to the same beacon contract that holds the implementation address.
contract BeaconProxy is Proxy, ERC1967Upgrade {
constructor(address beacon, bytes memory data);
}
contract UpgradeableBeacon is IBeacon, Ownable {
constructor(address implementation_);
function implementation() public view virtual override returns (address);
function upgradeTo(address newImplementation) public virtual onlyOwner;
function upgradeToAndCall(address newImplementation, bytes calldata data) public payable virtual onlyOwner;
}
interface IBeacon {
function implementation() external view returns (address);
}pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
contract TokenBeaconFactory {
UpgradeableBeacon public immutable beacon;
constructor(address tokenImplementation) {
beacon = new UpgradeableBeacon(tokenImplementation);
}
function createToken(string memory name, string memory symbol) external returns (address) {
bytes memory data = abi.encodeWithSelector(
IToken.initialize.selector,
name,
symbol,
msg.sender
);
return address(new BeaconProxy(address(beacon), data));
}
function upgradeAllTokens(address newImplementation) external {
beacon.upgradeTo(newImplementation);
}
}Base contract for initialization logic in upgradeable contracts, replacing constructors which don't work with proxies.
abstract contract Initializable {
modifier initializer();
modifier reinitializer(uint8 version);
modifier onlyInitializing();
function _disableInitializers() internal virtual;
function _getInitializedVersion() internal view returns (uint8);
function _isInitializing() internal view returns (bool);
}When implementing proxy patterns:
initializer modifier instead of constructors for proxy-compatible contractsProxy contracts may revert with implementation-specific errors plus:
ERC1967InvalidImplementation(address implementation), ERC1967InvalidAdmin(address admin), ERC1967InvalidBeacon(address beacon)UUPSUpgradeable__Unauthorized(), UUPSUpgradeable__InvalidImplementation()InvalidInitialization(), NotInitializing()Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin-solidity