// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ForgeDeploy_Proxy.sol"; interface ERC165 { function supportsInterface(bytes4 id) external view returns (bool); } ///@notice Proxy implementing EIP173 for ownership management contract EIP173Proxy is Proxy { // ////////////////////////// EVENTS /////////////////////////////////////////////////////////////////////// event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // /////////////////////// CONSTRUCTOR ////////////////////////////////////////////////////////////////////// constructor( address implementationAddress, address ownerAddress, bytes memory data ) payable { _setImplementation(implementationAddress, data); _setOwner(ownerAddress); } // ///////////////////// EXTERNAL /////////////////////////////////////////////////////////////////////////// function owner() external view returns (address) { return _owner(); } function supportsInterface(bytes4 id) external view returns (bool) { if (id == 0x01ffc9a7 || id == 0x7f5828d0) { return true; } if (id == 0xFFFFFFFF) { return false; } ERC165 implementation; // solhint-disable-next-line security/no-inline-assembly assembly { implementation := sload(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc) } // Technically this is not standard compliant as ERC-165 require 30,000 gas which that call cannot ensure // because it is itself inside `supportsInterface` that might only get 30,000 gas. // In practise this is unlikely to be an issue. try implementation.supportsInterface(id) returns (bool support) { return support; } catch { return false; } } function transferOwnership(address newOwner) external onlyOwner { _setOwner(newOwner); } function upgradeTo(address newImplementation) external onlyOwner { _setImplementation(newImplementation, ""); } function upgradeToAndCall(address newImplementation, bytes calldata data) external payable onlyOwner { _setImplementation(newImplementation, data); } // /////////////////////// MODIFIERS //////////////////////////////////////////////////////////////////////// modifier onlyOwner() { require(msg.sender == _owner(), "NOT_AUTHORIZED"); _; } // ///////////////////////// INTERNAL ////////////////////////////////////////////////////////////////////// function _owner() internal view returns (address adminAddress) { // solhint-disable-next-line security/no-inline-assembly assembly { adminAddress := sload(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103) } } function _setOwner(address newOwner) internal { address previousOwner = _owner(); // solhint-disable-next-line security/no-inline-assembly assembly { sstore(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103, newOwner) } emit OwnershipTransferred(previousOwner, newOwner); } }