creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ArraysUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Arrays.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./StorageSlotUpgradeable.sol\";\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev Collection of functions related to array types.\n */\nlibrary ArraysUpgradeable {\n    using StorageSlotUpgradeable for bytes32;\n\n    /**\n     * @dev Searches a sorted `array` and returns the first index that contains\n     * a value greater or equal to `element`. If no such index exists (i.e. all\n     * values in the array are strictly less than `element`), the array length is\n     * returned. Time complexity O(log n).\n     *\n     * `array` is expected to be sorted in ascending order, and to contain no\n     * repeated elements.\n     */\n    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        if (array.length == 0) {\n            return 0;\n        }\n\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        while (low < high) {\n            uint256 mid = MathUpgradeable.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds down (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\n        if (low > 0 && unsafeAccess(array, low - 1).value == element) {\n            return low - 1;\n        } else {\n            return low;\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlotUpgradeable.AddressSlot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getAddressSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlotUpgradeable.Bytes32Slot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getBytes32Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlotUpgradeable.Uint256Slot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getUint256Slot();\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n}\n"
      },
      "contracts/common/Merkle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n * @title Merkle\n * @author QEDK\n * @notice Gas optimized verification of proof of inclusion for a leaf in an ordered Merkle tree\n */\nlibrary Merkle {\n    /**\n     * @notice checks membership of a leaf in a merkle tree\n     * @param leaf keccak256 hash to check the membership of\n     * @param index position of the hash in the tree\n     * @param rootHash root hash of the merkle tree\n     * @param proof an array of hashes needed to prove the membership of the leaf\n     * @return isMember boolean value indicating if the leaf is in the tree or not\n     */\n    function checkMembership(\n        bytes32 leaf,\n        uint256 index,\n        bytes32 rootHash,\n        bytes32[] calldata proof\n    ) internal pure returns (bool isMember) {\n        // solhint-disable-next-line no-inline-assembly\n        // slither-disable-next-line assembly\n        assembly (\"memory-safe\") {\n            // if proof is empty, check if the leaf is the root\n            if proof.length {\n                // set end to be the end of the proof array, shl(5, proof.length) is equivalent to proof.length * 32\n                let end := add(proof.offset, shl(5, proof.length))\n                // set iterator to the start of the proof array\n                let i := proof.offset\n                // prettier-ignore\n                // solhint-disable-next-line no-empty-blocks\n                for {} 1 {} {\n                    // if index is odd, leaf slot is at 0x20, else 0x0\n                    let leafSlot := shl(5, and(0x1, index))\n                    // store the leaf at the calculated slot\n                    mstore(leafSlot, leaf)\n                    // store proof element in whichever slot is not occupied by the leaf\n                    mstore(xor(leafSlot, 32), calldataload(i))\n                    // hash the first 64 bytes in memory\n                    leaf := keccak256(0, 64)\n                    // shift index right by 1 bit to divide by 2\n                    index := shr(1, index)\n                    // increment iterator by 32 bytes\n                    i := add(i, 32)\n                    // break if iterator is at the end of the proof array\n                    if iszero(lt(i, end)) {\n                        break\n                    }\n                }\n            }\n            // checks if the calculated root matches the expected root\n            // then, check if index was zeroed while calculating proof, else an invalid index was provided\n            isMember := and(eq(leaf, rootHash), iszero(index))\n        }\n    }\n\n    /**\n     * @notice checks membership of a leaf in a merkle tree with expected height\n     * @param leaf keccak256 hash to check the membership of\n     * @param index position of the hash in the tree\n     * @param numLeaves number of leaves in the merkle tree (used to check the proof length)\n     * @param rootHash root hash of the merkle tree\n     * @param proof an array of hashes needed to prove the membership of the leaf\n     * @return isMember a boolean value indicating if the leaf is in the tree or not\n     */\n    function checkMembershipWithHeight(\n        bytes32 leaf,\n        uint256 index,\n        uint256 numLeaves,\n        bytes32 rootHash,\n        bytes32[] calldata proof\n    ) internal pure returns (bool isMember) {\n        // solhint-disable-next-line no-inline-assembly\n        // slither-disable-next-line assembly\n        assembly (\"memory-safe\") {\n            // if proof is empty, check if the leaf is the root\n            if proof.length {\n                // set end to be the end of the proof array, shl(5, proof.length) is equivalent to proof.length * 32\n                let end := add(proof.offset, shl(5, proof.length))\n                // set iterator to the start of the proof array\n                let i := proof.offset\n                // prettier-ignore\n                // solhint-disable-next-line no-empty-blocks\n                for {} 1 {} {\n                    // if index is odd, leaf slot is at 0x20, else 0x0\n                    let leafSlot := shl(5, and(0x1, index))\n                    // store the leaf at the calculated slot\n                    mstore(leafSlot, leaf)\n                    // store proof element in whichever slot is not occupied by the leaf\n                    mstore(xor(leafSlot, 32), calldataload(i))\n                    // hash the first 64 bytes in memory\n                    leaf := keccak256(0, 64)\n                    // shift index right by 1 bit to divide by 2\n                    index := shr(1, index)\n                    // increment iterator by 32 bytes\n                    i := add(i, 32)\n                    // break if iterator is at the end of the proof array\n                    if iszero(lt(i, end)) {\n                        break\n                    }\n                }\n            }\n            // check if log2(numLeaves) is an integer, or else rounds up to the next integer\n            // then, checks if the calculated root matches the expected root\n            // finally, checks if index was zeroed while calculating proof, else an invalid index was provided\n            // slither-disable-next-line incorrect-shift\n            isMember := and(\n                and(lt(numLeaves, add(shl(proof.length, 0x1), 1)), gt(numLeaves, shl(sub(proof.length, 1), 0x1))),\n                and(eq(leaf, rootHash), iszero(index))\n            )\n        }\n    }\n}\n"
      },
      "contracts/interfaces/common/IBLS.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IBLS {\n    /**\n     * @notice verifies a single signature\n     * @param signature 64-byte G1 group element (small sig)\n     * @param pubkey 128-byte G2 group element (big pubkey)\n     * @param message message signed to produce signature\n     * @return bool sig verification\n     * @return bool indicating call success\n     */\n    function verifySingle(\n        uint256[2] calldata signature,\n        uint256[4] calldata pubkey,\n        uint256[2] calldata message\n    ) external view returns (bool, bool);\n\n    /**\n     * @notice verifies multiple non-aggregated signatures where each message is unique\n     * @param signature 64-byte G1 group element (small sig)\n     * @param pubkeys array of 128-byte G2 group element (big pubkey)\n     * @param messages array of messages signed to produce signature\n     * @return checkResult bool indicating sig verification\n     * @return callSuccess bool indicating call success\n     */\n    function verifyMultiple(\n        uint256[2] calldata signature,\n        uint256[4][] calldata pubkeys,\n        uint256[2][] calldata messages\n    ) external view returns (bool checkResult, bool callSuccess);\n\n    /**\n     * @notice verifies an aggregated signature where the same message is signed\n     * @param signature 64-byte G1 group element (small sig)\n     * @param pubkeys array of 128-byte G2 group element (big pubkey)\n     * @param message message signed by all to produce signature\n     * @return checkResult sig verification\n     * @return callSuccess indicating call success\n     */\n    function verifyMultipleSameMsg(\n        uint256[2] calldata signature,\n        uint256[4][] calldata pubkeys,\n        uint256[2] calldata message\n    ) external view returns (bool checkResult, bool callSuccess);\n\n    /**\n     * @notice maps a field element to the curve\n     * @param _x a valid field element\n     * @return p the point on the curve the point is mapped to\n     */\n    function mapToPoint(uint256 _x) external pure returns (uint256[2] memory p);\n\n    /**\n     * @notice checks if a signature is formatted correctly and valid\n     * @dev will revert if improperly formatted, will return false if invalid\n     * @param signature the BLS signature\n     * @return bool indicating if the signature is valid or not\n     */\n    function isValidSignature(uint256[2] memory signature) external view returns (bool);\n\n    /**\n     * @notice checks if point in the finite field Fq (x,y) is on the G1 curve\n     * @param point array with x and y values of the point\n     * @return _isOnCurve bool indicating if the point is on the curve or not\n     */\n    function isOnCurveG1(uint256[2] memory point) external pure returns (bool _isOnCurve);\n\n    /**\n     * @notice checks if point in the finite field Fq (x,y) is on the G2 curve\n     * @param point array with x and y values of the point\n     * @return _isOnCurve bool indicating if the point is on the curve or not\n     */\n    function isOnCurveG2(uint256[4] memory point) external pure returns (bool _isOnCurve);\n\n    /**\n     * @notice hashes an arbitrary message to a point on the curve\n     * @dev Fouque-Tibouchi Hash to Curve\n     * @param domain domain separator for the hash\n     * @param message the message to map\n     * @return uint256[2] (x,y) point on the curve that the message maps to\n     */\n    function hashToPoint(bytes32 domain, bytes memory message) external view returns (uint256[2] memory);\n\n    /**\n     * @notice hashes an arbitrary message to a field element\n     * @param domain domain separator for the hash\n     * @param messages the messages to map\n     * @return uint256[2] (x,y) point of the field element that the message maps to\n     */\n    function hashToField(bytes32 domain, bytes memory messages) external view returns (uint256[2] memory);\n\n    /**\n     * @notice pads messages less than 96 bytes to 96 bytes for hashing\n     * @param domain domain separator for the hash\n     * @param message the message to pad\n     * @return bytes the padded message\n     */\n    function expandMsgTo96(bytes32 domain, bytes memory message) external pure returns (bytes memory);\n}\n"
      },
      "contracts/interfaces/common/IBN256G2.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IBN256G2 {\n    function ecTwistAdd(\n        uint256 pt1xx,\n        uint256 pt1xy,\n        uint256 pt1yx,\n        uint256 pt1yy,\n        uint256 pt2xx,\n        uint256 pt2xy,\n        uint256 pt2yx,\n        uint256 pt2yy\n    ) external view returns (uint256, uint256, uint256, uint256);\n}\n"
      },
      "contracts/interfaces/root/ICheckpointManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n    @title CheckpointManager\n    @author Polygon Technology\n    @notice Checkpoint manager contract used by validators to submit signed checkpoints as proof of canonical chain.\n    @dev The contract is used to submit checkpoints and verify that they have been signed as expected.\n    */\ninterface ICheckpointManager {\n    struct Checkpoint {\n        uint256 epoch;\n        uint256 blockNumber;\n        bytes32 eventRoot;\n    }\n\n    struct CheckpointMetadata {\n        bytes32 blockHash;\n        uint256 blockRound;\n        bytes32 currentValidatorSetHash;\n    }\n\n    struct Validator {\n        address _address;\n        uint256[4] blsKey;\n        uint256 votingPower;\n    }\n\n    /**\n     * @notice Function to submit a single checkpoint for an epoch to CheckpointManager\n     * @dev Contract internally verifies provided signature against stored validator set\n     * @param checkpointMetadata The checkpoint metadata to verify with the signature\n     * @param checkpoint The checkpoint to store\n     * @param signature The aggregated signature submitted by the proposer\n     * @param newValidatorSet The new validator set to store\n     * @param bitmap The bitmap of the old valdiator set that signed the message\n     */\n    function submit(\n        CheckpointMetadata calldata checkpointMetadata,\n        Checkpoint calldata checkpoint,\n        uint256[2] calldata signature,\n        Validator[] calldata newValidatorSet,\n        bytes calldata bitmap\n    ) external;\n\n    /**\n     * @notice Function to get if a event is part of the event root for a block number\n     * @param blockNumber The block number to get the event root from (i.e. blockN <-- eventRoot --> blockN+M)\n     * @param leaf The leaf of the event (keccak256-encoded log)\n     * @param leafIndex The leaf index of the event in the Merkle root tree\n     * @param proof The proof for leaf membership in the event root tree\n     */\n    function getEventMembershipByBlockNumber(\n        uint256 blockNumber,\n        bytes32 leaf,\n        uint256 leafIndex,\n        bytes32[] calldata proof\n    ) external view returns (bool);\n\n    /**\n     * @notice Function to get if a event is part of the event root for an epoch\n     * @param epoch The epoch id to get the event root for\n     * @param leaf The leaf of the event (keccak256-encoded log)\n     * @param leafIndex The leaf index of the event in the Merkle root tree\n     * @param proof The proof for leaf membership in the event root tree\n     */\n    function getEventMembershipByEpoch(\n        uint256 epoch,\n        bytes32 leaf,\n        uint256 leafIndex,\n        bytes32[] calldata proof\n    ) external view returns (bool);\n\n    /**\n     * @notice Function to get the checkpoint block number for a block number.\n     * It finds block number which is greater or equal than provided one in checkpointBlockNumbers array.\n     * @param blockNumber The block number to get the checkpoint block number for\n     * @return bool If block number was checkpointed\n     * @return uint256 The checkpoint block number\n     */\n    function getCheckpointBlock(uint256 blockNumber) external view returns (bool, uint256);\n\n    /**\n     * @notice Function to get the event root for a block number\n     * @param blockNumber The block number to get the event root for\n     */\n    function getEventRootByBlock(uint256 blockNumber) external view returns (bytes32);\n}\n"
      },
      "contracts/root/CheckpointManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ArraysUpgradeable.sol\";\nimport \"../common/Merkle.sol\";\nimport \"../interfaces/root/ICheckpointManager.sol\";\nimport \"../interfaces/common/IBLS.sol\";\nimport \"../interfaces/common/IBN256G2.sol\";\n\ncontract CheckpointManager is ICheckpointManager, Initializable {\n    using ArraysUpgradeable for uint256[];\n    using Merkle for bytes32;\n\n    bytes32 public constant DOMAIN = keccak256(\"DOMAIN_CHECKPOINT_MANAGER\");\n\n    uint256 public chainId;\n    uint256 public currentEpoch;\n    uint256 public currentValidatorSetLength;\n    uint256 public currentCheckpointBlockNumber;\n    uint256 public totalVotingPower;\n    IBLS public bls;\n    IBN256G2 public bn256G2;\n\n    mapping(uint256 => Checkpoint) public checkpoints; // epochId -> root\n    mapping(uint256 => Validator) public currentValidatorSet;\n    uint256[] public checkpointBlockNumbers;\n    bytes32 public currentValidatorSetHash;\n\n    // slither-disable-next-line naming-convention\n    address private immutable _INITIALIZER;\n\n    /// @notice If the contract is meant to be initialized at a later time, specifiy the address that will initialize it.\n    /// @notice Otherwise, pass `address(0)`.\n    constructor(address INITIALIZER) {\n        // slither-disable-next-line missing-zero-check\n        _INITIALIZER = INITIALIZER;\n    }\n\n    /**\n     * @notice Initialization function for CheckpointManager\n     * @dev Contract can only be initialized once\n     * @param newBls Address of the BLS library contract\n     * @param newBn256G2 Address of the BLS library contract\n     * @param chainId_ Chain ID of the child chain\n     */\n    function initialize(\n        IBLS newBls,\n        IBN256G2 newBn256G2,\n        uint256 chainId_,\n        Validator[] calldata newValidatorSet\n    ) external initializer {\n        if (_INITIALIZER != address(0)) require(msg.sender == _INITIALIZER);\n\n        // slither-disable-start events-maths\n        chainId = chainId_;\n        bls = newBls;\n        bn256G2 = newBn256G2;\n        currentValidatorSetLength = newValidatorSet.length;\n        _setNewValidatorSet(newValidatorSet);\n        // slither-disable-end events-maths\n    }\n\n    /**\n     * @inheritdoc ICheckpointManager\n     */\n    function submit(\n        CheckpointMetadata calldata checkpointMetadata,\n        Checkpoint calldata checkpoint,\n        uint256[2] calldata signature,\n        Validator[] calldata newValidatorSet,\n        bytes calldata bitmap\n    ) external {\n        require(currentValidatorSetHash == checkpointMetadata.currentValidatorSetHash, \"INVALID_VALIDATOR_SET_HASH\");\n        bytes memory hash = abi.encode(\n            keccak256(\n                abi.encode(\n                    chainId,\n                    checkpoint.blockNumber,\n                    checkpointMetadata.blockHash,\n                    checkpointMetadata.blockRound,\n                    checkpoint.epoch,\n                    checkpoint.eventRoot,\n                    checkpointMetadata.currentValidatorSetHash,\n                    keccak256(abi.encode(newValidatorSet))\n                )\n            )\n        );\n\n        _verifySignature(bls.hashToPoint(DOMAIN, hash), signature, bitmap);\n\n        uint256 prevEpoch = currentEpoch;\n\n        _verifyCheckpoint(prevEpoch, checkpoint);\n\n        checkpoints[checkpoint.epoch] = checkpoint;\n\n        if (checkpoint.epoch > prevEpoch) {\n            // if new epoch, push new end block\n            checkpointBlockNumbers.push(checkpoint.blockNumber);\n            ++currentEpoch;\n        } else {\n            // update last end block if updating event root for epoch\n            checkpointBlockNumbers[checkpointBlockNumbers.length - 1] = checkpoint.blockNumber;\n        }\n\n        currentCheckpointBlockNumber = checkpoint.blockNumber;\n\n        _setNewValidatorSet(newValidatorSet);\n    }\n\n    /**\n     * @inheritdoc ICheckpointManager\n     */\n    function getEventMembershipByBlockNumber(\n        uint256 blockNumber,\n        bytes32 leaf,\n        uint256 leafIndex,\n        bytes32[] calldata proof\n    ) external view returns (bool) {\n        bytes32 eventRoot = getEventRootByBlock(blockNumber);\n        require(eventRoot != bytes32(0), \"NO_EVENT_ROOT_FOR_BLOCK_NUMBER\");\n        return leaf.checkMembership(leafIndex, eventRoot, proof);\n    }\n\n    /**\n     * @inheritdoc ICheckpointManager\n     */\n    function getEventMembershipByEpoch(\n        uint256 epoch,\n        bytes32 leaf,\n        uint256 leafIndex,\n        bytes32[] calldata proof\n    ) external view returns (bool) {\n        bytes32 eventRoot = checkpoints[epoch].eventRoot;\n        require(eventRoot != bytes32(0), \"NO_EVENT_ROOT_FOR_EPOCH\");\n        return leaf.checkMembership(leafIndex, eventRoot, proof);\n    }\n\n    /**\n     * @inheritdoc ICheckpointManager\n     */\n    function getCheckpointBlock(uint256 blockNumber) external view returns (bool, uint256) {\n        uint256 checkpointBlockIdx = checkpointBlockNumbers.findUpperBound(blockNumber);\n        if (checkpointBlockIdx == checkpointBlockNumbers.length) {\n            return (false, 0);\n        }\n        return (true, checkpointBlockNumbers[checkpointBlockIdx]);\n    }\n\n    /**\n     * @inheritdoc ICheckpointManager\n     */\n    function getEventRootByBlock(uint256 blockNumber) public view returns (bytes32) {\n        return checkpoints[checkpointBlockNumbers.findUpperBound(blockNumber) + 1].eventRoot;\n    }\n\n    function _setNewValidatorSet(Validator[] calldata newValidatorSet) private {\n        uint256 length = newValidatorSet.length;\n        currentValidatorSetLength = length;\n        currentValidatorSetHash = keccak256(abi.encode(newValidatorSet));\n        uint256 totalPower = 0;\n        for (uint256 i = 0; i < length; ++i) {\n            uint256 votingPower = newValidatorSet[i].votingPower;\n            require(votingPower > 0, \"VOTING_POWER_ZERO\");\n            totalPower += votingPower;\n            currentValidatorSet[i] = newValidatorSet[i];\n        }\n        totalVotingPower = totalPower;\n    }\n\n    /**\n     * @notice Internal function that asserts that the signature is valid and that the required threshold is met\n     * @param message The message that was signed by validators (i.e. checkpoint hash)\n     * @param signature The aggregated signature submitted by the proposer\n     */\n    function _verifySignature(\n        uint256[2] memory message,\n        uint256[2] calldata signature,\n        bytes calldata bitmap\n    ) private view {\n        uint256 length = currentValidatorSetLength;\n        // slither-disable-next-line uninitialized-local\n        uint256[4] memory aggPubkey;\n        uint256 aggVotingPower = 0;\n        for (uint256 i = 0; i < length; ) {\n            if (_getValueFromBitmap(bitmap, i)) {\n                if (aggVotingPower == 0) {\n                    aggPubkey = currentValidatorSet[i].blsKey;\n                } else {\n                    uint256[4] memory blsKey = currentValidatorSet[i].blsKey;\n                    // slither-disable-next-line calls-loop\n                    (aggPubkey[0], aggPubkey[1], aggPubkey[2], aggPubkey[3]) = bn256G2.ecTwistAdd(\n                        aggPubkey[0],\n                        aggPubkey[1],\n                        aggPubkey[2],\n                        aggPubkey[3],\n                        blsKey[0],\n                        blsKey[1],\n                        blsKey[2],\n                        blsKey[3]\n                    );\n                }\n                aggVotingPower += currentValidatorSet[i].votingPower;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n\n        require(aggVotingPower != 0, \"BITMAP_IS_EMPTY\");\n        require(aggVotingPower > ((2 * totalVotingPower) / 3), \"INSUFFICIENT_VOTING_POWER\");\n\n        (bool callSuccess, bool result) = bls.verifySingle(signature, aggPubkey, message);\n\n        require(callSuccess && result, \"SIGNATURE_VERIFICATION_FAILED\");\n    }\n\n    /**\n     * @notice Internal function that performs checks on the checkpoint\n     * @param prevId Current checkpoint ID\n     * @param checkpoint The checkpoint to store\n     */\n    function _verifyCheckpoint(uint256 prevId, Checkpoint calldata checkpoint) private view {\n        Checkpoint memory oldCheckpoint = checkpoints[prevId];\n        require(\n            checkpoint.epoch == oldCheckpoint.epoch || checkpoint.epoch == (oldCheckpoint.epoch + 1),\n            \"INVALID_EPOCH\"\n        );\n        require(checkpoint.blockNumber > oldCheckpoint.blockNumber, \"EMPTY_CHECKPOINT\");\n    }\n\n    function _getValueFromBitmap(bytes calldata bitmap, uint256 index) private pure returns (bool) {\n        uint256 byteNumber = index / 8;\n        uint8 bitNumber = uint8(index % 8);\n\n        if (byteNumber >= bitmap.length) {\n            return false;\n        }\n\n        // Get the value of the bit at the given 'index' in a byte.\n        return uint8(bitmap[byteNumber]) & (1 << bitNumber) > 0;\n    }\n\n    // slither-disable-next-line unused-state,naming-convention\n    uint256[50] private __gap;\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 115
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}