1// SPDX-License-Identifier: MIT2// OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/TransparentUpgradeableProxy.sol)34pragma solidity ^0.8.0;56import "../ERC1967/ERC1967Proxy.sol";78/**9 * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}10 * does not implement this interface directly, and some of its functions are implemented by an internal dispatch11 * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not12 * include them in the ABI so this interface must be used to interact with it.13 */14interface ITransparentUpgradeableProxy is IERC1967 {15 function admin() external view returns (address);1617 function implementation() external view returns (address);1819 function changeAdmin(address) external;2021 function upgradeTo(address) external;2223 function upgradeToAndCall(address, bytes memory) external payable;24}2526/**27 * @dev This contract implements a proxy that is upgradeable by an admin.28 *29 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector30 * clashing], which can potentially be used in an attack, this contract uses the31 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two32 * things that go hand in hand:33 *34 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if35 * that call matches one of the admin functions exposed by the proxy itself.36 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the37 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says38 * "admin cannot fallback to proxy target".39 *40 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing41 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due42 * to sudden errors when trying to call a function from the proxy implementation.43 *44 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,45 * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.46 *47 * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not48 * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch49 * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to50 * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the51 * implementation.52 *53 * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler54 * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function55 * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could56 * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.57 */58contract TransparentUpgradeableProxy is ERC1967Proxy {59 /**60 * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and61 * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.62 */63 constructor(64 address _logic,65 address admin_,66 bytes memory _data67 ) payable ERC1967Proxy(_logic, _data) {68 _changeAdmin(admin_);69 }7071 /**72 * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.73 *74 * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the75 * implementation provides a function with the same selector.76 */77 modifier ifAdmin() {78 if (msg.sender == _getAdmin()) {79 _;80 } else {81 _fallback();82 }83 }8485 /**86 * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior87 */88 function _fallback() internal virtual override {89 if (msg.sender == _getAdmin()) {90 bytes memory ret;91 bytes4 selector = msg.sig;92 if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {93 ret = _dispatchUpgradeTo();94 } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {95 ret = _dispatchUpgradeToAndCall();96 } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {97 ret = _dispatchChangeAdmin();98 } else if (selector == ITransparentUpgradeableProxy.admin.selector) {99 ret = _dispatchAdmin();100 } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {101 ret = _dispatchImplementation();102 } else {103 revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target");104 }105 assembly {106 return(add(ret, 0x20), mload(ret))107 }108 } else {109 super._fallback();110 }111 }112113 /**114 * @dev Returns the current admin.115 *116 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the117 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.118 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`119 */120 function _dispatchAdmin() private returns (bytes memory) {121 _requireZeroValue();122123 address admin = _getAdmin();124 return abi.encode(admin);125 }126127 /**128 * @dev Returns the current implementation.129 *130 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the131 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.132 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`133 */134 function _dispatchImplementation() private returns (bytes memory) {135 _requireZeroValue();136137 address implementation = _implementation();138 return abi.encode(implementation);139 }140141 /**142 * @dev Changes the admin of the proxy.143 *144 * Emits an {AdminChanged} event.145 */146 function _dispatchChangeAdmin() private returns (bytes memory) {147 _requireZeroValue();148149 address newAdmin = abi.decode(msg.data[4:], (address));150 _changeAdmin(newAdmin);151152 return "";153 }154155 /**156 * @dev Upgrade the implementation of the proxy.157 */158 function _dispatchUpgradeTo() private returns (bytes memory) {159 _requireZeroValue();160161 address newImplementation = abi.decode(msg.data[4:], (address));162 _upgradeToAndCall(newImplementation, bytes(""), false);163164 return "";165 }166167 /**168 * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified169 * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the170 * proxied contract.171 */172 function _dispatchUpgradeToAndCall() private returns (bytes memory) {173 (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));174 _upgradeToAndCall(newImplementation, data, true);175176 return "";177 }178179 /**180 * @dev Returns the current admin.181 */182 function _admin() internal view virtual returns (address) {183 return _getAdmin();184 }185186 /**187 * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to188 * emulate some proxy functions being non-payable while still allowing value to pass through.189 */190 function _requireZeroValue() private {191 require(msg.value == 0);192 }193}194