creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/TransparentUpgradableProxy.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\r\n\r\npragma solidity ^0.8.24;\r\n\r\n/**\r\n * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance.\r\n *\r\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\r\n * clashing], which can potentially be used in an attack, this contract uses the\r\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\r\n * things that go hand in hand:\r\n *\r\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\r\n * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.\r\n * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to\r\n * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating\r\n * the proxy admin cannot fallback to the target implementation.\r\n *\r\n * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a\r\n * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to\r\n * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and\r\n * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative\r\n * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership.\r\n *\r\n * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not\r\n * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch\r\n * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to\r\n * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the\r\n * implementation.\r\n *\r\n * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a\r\n * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract.\r\n *\r\n * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an\r\n * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be\r\n * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an\r\n * undesirable state where the admin slot is different from the actual admin.\r\n */\r\n\r\ncontract TransparentUpgradableProxy {\r\n\r\n    bytes32 private constant IMPLEMENTATION_SLOT = bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\r\n    bytes32 private constant ADMIN_SLOT = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\r\n\r\n    constructor(address _implementation) {\r\n        _setAdmin(msg.sender);\r\n        _setImplementation(_implementation);\r\n    }\r\n\r\n    modifier ifAdmin() {\r\n        if (msg.sender == _getAdmin()) {\r\n            _;\r\n        } else {\r\n            _fallback();\r\n        }\r\n    }\r\n\r\n    function _getAdmin() private view returns (address) {\r\n        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\r\n    }\r\n\r\n    function _setAdmin(address _admin) private {\r\n        require(_admin != address(0), \"admin = zero address\");\r\n        StorageSlot.getAddressSlot(ADMIN_SLOT).value = _admin;\r\n    }\r\n\r\n    function _getImplementation() private view returns (address) {\r\n        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\r\n    }\r\n\r\n    function _setImplementation(address _implementation) private {\r\n        require(\r\n            _implementation.code.length > 0, \"implementation is not contract\"\r\n        );\r\n        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation;\r\n    }\r\n\r\n    // Admin interface //\r\n    // 0x8f283970\r\n    function changeAdmin(address _admin) external ifAdmin {\r\n        _setAdmin(_admin);\r\n    }\r\n\r\n    // 0x3659cfe6\r\n    function upgradeTo(address _implementation) external ifAdmin {\r\n        _setImplementation(_implementation);\r\n    }\r\n\r\n    // 0x4f1ef286\r\n    function upgradeToAndCall(address _implementation, bytes memory data) external ifAdmin {\r\n        require(_implementation.code.length > 0, \"Invalid implementation address\");\r\n        _setImplementation(_implementation);\r\n\r\n        if (data.length > 0) {\r\n            _implementation.delegatecall(data);\r\n        }\r\n    }\r\n\r\n    // 0xf851a440\r\n    function admin() external ifAdmin returns (address) {\r\n        return _getAdmin();\r\n    }\r\n\r\n    // 0x5c60da1b\r\n    function implementation() external ifAdmin returns (address) {\r\n        return _getImplementation();\r\n    }\r\n\r\n    // User interface //\r\n    function _delegate(address _implementation) internal {\r\n        assembly {\r\n        // Copy msg.data. We take full control of memory in this inline assembly\r\n        // block because it will not return to Solidity code. We overwrite the\r\n        // Solidity scratch pad at memory position 0.\r\n\r\n        // calldatacopy(t, f, s) - copy s bytes from calldata at position f to mem at position t\r\n        // calldatasize() - size of call data in bytes\r\n            calldatacopy(0, 0, calldatasize())\r\n\r\n        // Call the implementation.\r\n        // out and outsize are 0 because we don't know the size yet.\r\n\r\n        // delegatecall(g, a, in, insize, out, outsize) -\r\n        // - call contract at address a\r\n        // - with input mem[in…(in+insize))\r\n        // - providing g gas\r\n        // - and output area mem[out…(out+outsize))\r\n        // - returning 0 on error (eg. out of gas) and 1 on success\r\n            let result :=\r\n            delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)\r\n\r\n        // Copy the returned data.\r\n        // returndatacopy(t, f, s) - copy s bytes from returndata at position f to mem at position t\r\n        // returndatasize() - size of the last returndata\r\n            returndatacopy(0, 0, returndatasize())\r\n\r\n            switch result\r\n            // delegatecall returns 0 on error.\r\n            case 0 {\r\n            // revert(p, s) - end execution, revert state changes, return data mem[p…(p+s))\r\n                revert(0, returndatasize())\r\n            }\r\n            default {\r\n            // return(p, s) - end execution, return data mem[p…(p+s))\r\n                return(0, returndatasize())\r\n            }\r\n        }\r\n    }\r\n\r\n    function _fallback() private {\r\n        _delegate(_getImplementation());\r\n    }\r\n\r\n    fallback() external payable {\r\n        _fallback();\r\n    }\r\n\r\n    receive() external payable {\r\n        _fallback();\r\n    }\r\n}\r\n\r\n// Storage slot library\r\nlibrary StorageSlot {\r\n    struct AddressSlot {\r\n        address value;\r\n    }\r\n\r\n    function getAddressSlot(bytes32 slot)\r\n    internal\r\n    pure\r\n    returns (AddressSlot storage r)\r\n    {\r\n        assembly {\r\n            r.slot := slot\r\n        }\r\n    }\r\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}