CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-openzeppelin-solidity

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.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

proxy.mddocs/

Proxy Patterns

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.

Core Imports

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";

Capabilities

Minimal Proxy (EIP-1167)

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);
}

Usage Example

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

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;
}

ERC-1967 Proxy Standard

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 Upgradeable Proxy

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;
}

Usage Example

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)

UUPS Upgradeable Pattern

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;
}

Usage Example

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;
    }
}

Beacon Proxy Pattern

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);
}

Usage Example

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);
    }
}

Initializable Pattern

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);
}

Proxy Pattern Best Practices

When implementing proxy patterns:

  1. Storage Layout: Maintain storage layout compatibility between implementation versions
  2. Initialization: Use initializer modifier instead of constructors for proxy-compatible contracts
  3. Admin Security: Protect upgrade functions with proper access control
  4. Testing: Test upgrade scenarios thoroughly, including storage layout changes
  5. Selector Clashes: Be aware of potential function selector clashes in transparent proxies
  6. Gas Costs: Consider gas costs of different proxy patterns for your use case

Proxy Pattern Comparison

  • Minimal Proxy: Cheapest deployment, immutable implementation
  • Transparent Proxy: Most flexible, higher gas costs due to admin checks
  • UUPS: Lower gas costs than transparent, upgrade logic in implementation
  • Beacon Proxy: Best for multiple proxies sharing the same implementation

Error Handling

Proxy contracts may revert with implementation-specific errors plus:

  • ERC1967Upgrade: ERC1967InvalidImplementation(address implementation), ERC1967InvalidAdmin(address admin), ERC1967InvalidBeacon(address beacon)
  • UUPSUpgradeable: UUPSUpgradeable__Unauthorized(), UUPSUpgradeable__InvalidImplementation()
  • Initializable: InvalidInitialization(), NotInitializing()

Install with Tessl CLI

npx tessl i tessl/npm-openzeppelin-solidity

docs

access-control.md

crosschain.md

finance.md

governance.md

index.md

metatx.md

proxy.md

security.md

tokens.md

utilities.md

tile.json