// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.6.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.22; import {Proxy} from "../Proxy.sol"; import {ERC1967Utils} from "./ERC1967Utils.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy { /** * @dev The proxy is left uninitialized. */ error ERC1967ProxyUninitialized(); /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`. * * Provided `_data` is passed in a delegate call to `implementation`. This will typically be an encoded function * call, and allows initializing the storage of the proxy like a Solidity constructor. By default construction * will fail if `_data` is empty. This behavior can be overridden using a custom {_unsafeAllowUninitialized} that * returns true. In that case, empty `_data` is ignored and no delegate call to the implementation is performed * during construction. * * Requirements: * * - If `data` is empty, `msg.value` must be zero. */ constructor(address implementation, bytes memory _data) payable { if (!_unsafeAllowUninitialized() && _data.length == 0) { revert ERC1967ProxyUninitialized(); } ERC1967Utils.upgradeToAndCall(implementation, _data); } /** * @dev Returns the current implementation address. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _implementation() internal view virtual override returns (address) { return ERC1967Utils.getImplementation(); } /** * @dev Returns whether the proxy can be left uninitialized. * * NOTE: Override this function to allow the proxy to be left uninitialized. * Consider uninitialized proxies might be susceptible to man-in-the-middle threats * where the proxy is replaced with a malicious one. */ function _unsafeAllowUninitialized() internal pure virtual returns (bool) { return false; } }