creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\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 Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\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 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\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        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\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        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._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 _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC1822Proxiable} from \"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    address private immutable __self = address(this);\n\n    /**\n     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n     * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n     * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n     * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n     * during an upgrade.\n     */\n    string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n    /**\n     * @dev The call is from an unauthorized context.\n     */\n    error UUPSUnauthorizedCallContext();\n\n    /**\n     * @dev The storage `slot` is unsupported as a UUID.\n     */\n    error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        _checkProxy();\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        _checkNotDelegated();\n        _;\n    }\n\n    function __UUPSUpgradeable_init() internal onlyInitializing {\n    }\n\n    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual notDelegated returns (bytes32) {\n        return ERC1967Utils.IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     *\n     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data);\n    }\n\n    /**\n     * @dev Reverts if the execution is not performed via delegatecall or the execution\n     * context is not of a proxy with an ERC1967-compliant implementation pointing to self.\n     * See {_onlyProxy}.\n     */\n    function _checkProxy() internal view virtual {\n        if (\n            address(this) == __self || // Must be called through delegatecall\n            ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n        ) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Reverts if the execution is performed via delegatecall.\n     * See {notDelegated}.\n     */\n    function _checkNotDelegated() internal view virtual {\n        if (address(this) != __self) {\n            // Must not be called through delegatecall\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n\n    /**\n     * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n     *\n     * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n     * is expected to be the implementation slot in ERC1967.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n            if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n                revert UUPSUnsupportedProxiableUUID(slot);\n            }\n            ERC1967Utils.upgradeToAndCall(newImplementation, data);\n        } catch {\n            // The implementation is not UUPS\n            revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"
      },
      "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/interfaces/IERC5267.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.20;\n\ninterface IERC5267 {\n    /**\n     * @dev MAY be emitted to signal that the domain could have changed.\n     */\n    event EIP712DomainChanged();\n\n    /**\n     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n     * signature.\n     */\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"
      },
      "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {UpgradeableBeacon} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"
      },
      "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n */\nlibrary ERC1967Utils {\n    // We re-declare ERC-1967 events here because they can't be used directly from IERC1967.\n    // This will be fixed in Solidity 0.8.21. At that point we should remove these events.\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Emitted when the beacon is changed.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev The `implementation` of the proxy is invalid.\n     */\n    error ERC1967InvalidImplementation(address implementation);\n\n    /**\n     * @dev The `admin` of the proxy is invalid.\n     */\n    error ERC1967InvalidAdmin(address admin);\n\n    /**\n     * @dev The `beacon` of the proxy is invalid.\n     */\n    error ERC1967InvalidBeacon(address beacon);\n\n    /**\n     * @dev An upgrade function sees `msg.value > 0` that may be lost.\n     */\n    error ERC1967NonPayable();\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        if (newImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(newImplementation);\n        }\n        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(newImplementation, data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using\n     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        if (newAdmin == address(0)) {\n            revert ERC1967InvalidAdmin(address(0));\n        }\n        StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {IERC1967-AdminChanged} event.\n     */\n    function changeAdmin(address newAdmin) internal {\n        emit AdminChanged(getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        if (newBeacon.code.length == 0) {\n            revert ERC1967InvalidBeacon(newBeacon);\n        }\n\n        StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n        address beaconImplementation = IBeacon(newBeacon).implementation();\n        if (beaconImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(beaconImplementation);\n        }\n    }\n\n    /**\n     * @dev Change the beacon and trigger a setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-BeaconUpgraded} event.\n     *\n     * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n     * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n     * efficiency.\n     */\n    function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n     * if an upgrade doesn't perform an initialization call.\n     */\n    function _checkNonPayable() private {\n        if (msg.value > 0) {\n            revert ERC1967NonPayable();\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) 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 FailedInnerCall();\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the Merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates Merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n    /**\n     *@dev The multiproof provided is not valid.\n     */\n    error MerkleProofInvalidMultiproof();\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     */\n    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProof(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Calldata version of {verify}\n     */\n    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProofCalldata(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leafs & pre-images are assumed to be sorted.\n     */\n    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Calldata version of {processProof}\n     */\n    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function multiProofVerify(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProof(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Calldata version of {multiProofVerify}\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function multiProofVerifyCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     */\n    function processMultiProof(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofLen = proof.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proofLen != totalHashes + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            if (proofPos != proofLen) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[totalHashes - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Calldata version of {processMultiProof}.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function processMultiProofCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofLen = proof.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proofLen != totalHashes + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            if (proofPos != proofLen) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[totalHashes - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Sorts the pair (a, b) and hashes the result.\n     */\n    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n    }\n\n    /**\n     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.\n     */\n    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, a)\n            mstore(0x20, b)\n            value := keccak256(0x00, 0x40)\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\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 towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\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\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * 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 = x * y; // 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                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            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\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.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\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\n            // works 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 (unsignedRoundsUp(rounding) && 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\n     * towards zero.\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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\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(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n */\nlibrary StorageSlot {\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/base/Multicall.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.22;\n\nimport '../interfaces/IMulticall.sol';\n\n/**\n * @title Multicall\n * @author Uniswap\n * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol\n * @notice Enables calling multiple methods in a single call to the contract\n */\nabstract contract Multicall is IMulticall {\n  /// @inheritdoc IMulticall\n  function multicall(bytes[] calldata data) external override returns (bytes[] memory results) {\n    uint256 dataLength = data.length;\n    results = new bytes[](dataLength);\n    for (uint256 i = 0; i < dataLength; i++) {\n      (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n      if (!success) {\n        // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n        if (result.length < 68) revert();\n        assembly {\n          result := add(result, 0x04)\n        }\n        revert(abi.decode(result, (string)));\n      }\n\n      results[i] = result;\n    }\n  }\n}\n"
      },
      "contracts/interfaces/IEthFoxVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultAdmin} from './IVaultAdmin.sol';\nimport {IVaultVersion} from './IVaultVersion.sol';\nimport {IVaultFee} from './IVaultFee.sol';\nimport {IVaultState} from './IVaultState.sol';\nimport {IVaultValidators} from './IVaultValidators.sol';\nimport {IVaultEnterExit} from './IVaultEnterExit.sol';\nimport {IVaultOsToken} from './IVaultOsToken.sol';\nimport {IVaultMev} from './IVaultMev.sol';\nimport {IVaultEthStaking} from './IVaultEthStaking.sol';\nimport {IVaultBlocklist} from './IVaultBlocklist.sol';\nimport {IMulticall} from './IMulticall.sol';\n\n/**\n * @title IEthFoxVault\n * @author StakeWise\n * @notice Defines the interface for the EthFoxVault contract\n */\ninterface IEthFoxVault is\n  IVaultAdmin,\n  IVaultVersion,\n  IVaultFee,\n  IVaultState,\n  IVaultValidators,\n  IVaultEnterExit,\n  IVaultMev,\n  IVaultEthStaking,\n  IVaultBlocklist,\n  IMulticall\n{\n  /**\n   * @notice Event emitted when a user is ejected from the Vault\n   * @param user The address of the user\n   * @param shares The amount of shares ejected\n   */\n  event UserEjected(address user, uint256 shares);\n\n  /**\n   * @dev Struct for initializing the EthFoxVault contract\n   * @param admin The address of the Vault admin\n   * @param ownMevEscrow The address of the MEV escrow contract\n   * @param capacity The Vault stops accepting deposits after exceeding the capacity\n   * @param feePercent The fee percent that is charged by the Vault\n   * @param metadataIpfsHash The IPFS hash of the Vault's metadata file\n   */\n  struct EthFoxVaultInitParams {\n    address admin;\n    address ownMevEscrow;\n    uint256 capacity;\n    uint16 feePercent;\n    string metadataIpfsHash;\n  }\n\n  /**\n   * @notice Event emitted on EthFoxVault creation\n   * @param admin The address of the Vault admin\n   * @param ownMevEscrow The address of the MEV escrow contract\n   * @param capacity The capacity of the Vault\n   * @param feePercent The fee percent of the Vault\n   * @param metadataIpfsHash The IPFS hash of the Vault metadata\n   */\n  event EthFoxVaultCreated(\n    address admin,\n    address ownMevEscrow,\n    uint256 capacity,\n    uint16 feePercent,\n    string metadataIpfsHash\n  );\n\n  /**\n   * @notice Initializes the EthFoxVault contract. Must transfer security deposit together with a call.\n   * @param params The encoded parameters for initializing the EthFoxVault contract\n   */\n  function initialize(bytes calldata params) external payable;\n\n  /**\n   * @notice Ejects user from the Vault. Can only be called by the blocklist manager.\n   *         The ejected user will be added to the blocklist and all his shares will be sent to the exit queue.\n   * @param user The address of the user to eject\n   */\n  function ejectUser(address user) external;\n}\n"
      },
      "contracts/interfaces/IEthValidatorsRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\n\npragma solidity =0.8.22;\n\nimport {IValidatorsRegistry} from './IValidatorsRegistry.sol';\n\n/**\n * @title IEthValidatorsRegistry\n * @author Ethereum Foundation\n * @notice This is the Ethereum validators deposit contract interface.\n *         See https://github.com/ethereum/consensus-specs/blob/v1.2.0/solidity_deposit_contract/deposit_contract.sol.\n *         For more information see the Phase 0 specification under https://github.com/ethereum/consensus-specs.\n */\ninterface IEthValidatorsRegistry is IValidatorsRegistry {\n  /// @notice Submit a Phase 0 DepositData object.\n  /// @param pubkey A BLS12-381 public key.\n  /// @param withdrawal_credentials Commitment to a public key for withdrawals.\n  /// @param signature A BLS12-381 signature.\n  /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.\n  /// Used as a protection against malformed input.\n  function deposit(\n    bytes calldata pubkey,\n    bytes calldata withdrawal_credentials,\n    bytes calldata signature,\n    bytes32 deposit_data_root\n  ) external payable;\n}\n"
      },
      "contracts/interfaces/IKeeperOracles.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IERC5267} from '@openzeppelin/contracts/interfaces/IERC5267.sol';\n\n/**\n * @title IKeeperOracles\n * @author StakeWise\n * @notice Defines the interface for the KeeperOracles contract\n */\ninterface IKeeperOracles is IERC5267 {\n  /**\n   * @notice Event emitted on the oracle addition\n   * @param oracle The address of the added oracle\n   */\n  event OracleAdded(address indexed oracle);\n\n  /**\n   * @notice Event emitted on the oracle removal\n   * @param oracle The address of the removed oracle\n   */\n  event OracleRemoved(address indexed oracle);\n\n  /**\n   * @notice Event emitted on oracles config update\n   * @param configIpfsHash The IPFS hash of the new config\n   */\n  event ConfigUpdated(string configIpfsHash);\n\n  /**\n   * @notice Function for verifying whether oracle is registered or not\n   * @param oracle The address of the oracle to check\n   * @return `true` for the registered oracle, `false` otherwise\n   */\n  function isOracle(address oracle) external view returns (bool);\n\n  /**\n   * @notice Total Oracles\n   * @return The total number of oracles registered\n   */\n  function totalOracles() external view returns (uint256);\n\n  /**\n   * @notice Function for adding oracle to the set\n   * @param oracle The address of the oracle to add\n   */\n  function addOracle(address oracle) external;\n\n  /**\n   * @notice Function for removing oracle from the set\n   * @param oracle The address of the oracle to remove\n   */\n  function removeOracle(address oracle) external;\n\n  /**\n   * @notice Function for updating the config IPFS hash\n   * @param configIpfsHash The new config IPFS hash\n   */\n  function updateConfig(string calldata configIpfsHash) external;\n}\n"
      },
      "contracts/interfaces/IKeeperRewards.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IKeeperOracles} from './IKeeperOracles.sol';\n\n/**\n * @title IKeeperRewards\n * @author StakeWise\n * @notice Defines the interface for the Keeper contract rewards\n */\ninterface IKeeperRewards is IKeeperOracles {\n  /**\n   * @notice Event emitted on rewards update\n   * @param caller The address of the function caller\n   * @param rewardsRoot The new rewards merkle tree root\n   * @param avgRewardPerSecond The new average reward per second\n   * @param updateTimestamp The update timestamp used for rewards calculation\n   * @param nonce The nonce used for verifying signatures\n   * @param rewardsIpfsHash The new rewards IPFS hash\n   */\n  event RewardsUpdated(\n    address indexed caller,\n    bytes32 indexed rewardsRoot,\n    uint256 avgRewardPerSecond,\n    uint64 updateTimestamp,\n    uint64 nonce,\n    string rewardsIpfsHash\n  );\n\n  /**\n   * @notice Event emitted on Vault harvest\n   * @param vault The address of the Vault\n   * @param rewardsRoot The rewards merkle tree root\n   * @param totalAssetsDelta The Vault total assets delta since last sync. Can be negative in case of penalty/slashing.\n   * @param unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults.\n   */\n  event Harvested(\n    address indexed vault,\n    bytes32 indexed rewardsRoot,\n    int256 totalAssetsDelta,\n    uint256 unlockedMevDelta\n  );\n\n  /**\n   * @notice Event emitted on rewards min oracles number update\n   * @param oracles The new minimum number of oracles required to update rewards\n   */\n  event RewardsMinOraclesUpdated(uint256 oracles);\n\n  /**\n   * @notice A struct containing the last synced Vault's cumulative reward\n   * @param assets The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing.\n   * @param nonce The nonce of the last sync\n   */\n  struct Reward {\n    int192 assets;\n    uint64 nonce;\n  }\n\n  /**\n   * @notice A struct containing the last unlocked Vault's cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults.\n   * @param assets The shared MEV Vault's cumulative execution reward that can be withdrawn\n   * @param nonce The nonce of the last sync\n   */\n  struct UnlockedMevReward {\n    uint192 assets;\n    uint64 nonce;\n  }\n\n  /**\n   * @notice A struct containing parameters for rewards update\n   * @param rewardsRoot The new rewards merkle root\n   * @param avgRewardPerSecond The new average reward per second\n   * @param updateTimestamp The update timestamp used for rewards calculation\n   * @param rewardsIpfsHash The new IPFS hash with all the Vaults' rewards for the new root\n   * @param signatures The concatenation of the Oracles' signatures\n   */\n  struct RewardsUpdateParams {\n    bytes32 rewardsRoot;\n    uint256 avgRewardPerSecond;\n    uint64 updateTimestamp;\n    string rewardsIpfsHash;\n    bytes signatures;\n  }\n\n  /**\n   * @notice A struct containing parameters for harvesting rewards. Can only be called by Vault.\n   * @param rewardsRoot The rewards merkle root\n   * @param reward The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing.\n   * @param unlockedMevReward The Vault cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults.\n   * @param proof The proof to verify that Vault's reward is correct\n   */\n  struct HarvestParams {\n    bytes32 rewardsRoot;\n    int160 reward;\n    uint160 unlockedMevReward;\n    bytes32[] proof;\n  }\n\n  /**\n   * @notice Previous Rewards Root\n   * @return The previous merkle tree root of the rewards accumulated by the Vaults\n   */\n  function prevRewardsRoot() external view returns (bytes32);\n\n  /**\n   * @notice Rewards Root\n   * @return The latest merkle tree root of the rewards accumulated by the Vaults\n   */\n  function rewardsRoot() external view returns (bytes32);\n\n  /**\n   * @notice Rewards Nonce\n   * @return The nonce used for updating rewards merkle tree root\n   */\n  function rewardsNonce() external view returns (uint64);\n\n  /**\n   * @notice The last rewards update\n   * @return The timestamp of the last rewards update\n   */\n  function lastRewardsTimestamp() external view returns (uint64);\n\n  /**\n   * @notice The minimum number of oracles required to update rewards\n   * @return The minimum number of oracles\n   */\n  function rewardsMinOracles() external view returns (uint256);\n\n  /**\n   * @notice The rewards delay\n   * @return The delay in seconds between rewards updates\n   */\n  function rewardsDelay() external view returns (uint256);\n\n  /**\n   * @notice Get last synced Vault cumulative reward\n   * @param vault The address of the Vault\n   * @return assets The last synced reward assets\n   * @return nonce The last synced reward nonce\n   */\n  function rewards(address vault) external view returns (int192 assets, uint64 nonce);\n\n  /**\n   * @notice Get last unlocked shared MEV Vault cumulative reward\n   * @param vault The address of the Vault\n   * @return assets The last synced reward assets\n   * @return nonce The last synced reward nonce\n   */\n  function unlockedMevRewards(address vault) external view returns (uint192 assets, uint64 nonce);\n\n  /**\n   * @notice Checks whether Vault must be harvested\n   * @param vault The address of the Vault\n   * @return `true` if the Vault requires harvesting, `false` otherwise\n   */\n  function isHarvestRequired(address vault) external view returns (bool);\n\n  /**\n   * @notice Checks whether the Vault can be harvested\n   * @param vault The address of the Vault\n   * @return `true` if Vault can be harvested, `false` otherwise\n   */\n  function canHarvest(address vault) external view returns (bool);\n\n  /**\n   * @notice Checks whether rewards can be updated\n   * @return `true` if rewards can be updated, `false` otherwise\n   */\n  function canUpdateRewards() external view returns (bool);\n\n  /**\n   * @notice Checks whether the Vault has registered validators\n   * @param vault The address of the Vault\n   * @return `true` if Vault is collateralized, `false` otherwise\n   */\n  function isCollateralized(address vault) external view returns (bool);\n\n  /**\n   * @notice Update rewards data\n   * @param params The struct containing rewards update parameters\n   */\n  function updateRewards(RewardsUpdateParams calldata params) external;\n\n  /**\n   * @notice Harvest rewards. Can be called only by Vault.\n   * @param params The struct containing rewards harvesting parameters\n   * @return totalAssetsDelta The total reward/penalty accumulated by the Vault since the last sync\n   * @return unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults.\n   * @return harvested `true` when the rewards were harvested, `false` otherwise\n   */\n  function harvest(\n    HarvestParams calldata params\n  ) external returns (int256 totalAssetsDelta, uint256 unlockedMevDelta, bool harvested);\n\n  /**\n   * @notice Set min number of oracles for confirming rewards update. Can only be called by the owner.\n   * @param _rewardsMinOracles The new min number of oracles for confirming rewards update\n   */\n  function setRewardsMinOracles(uint256 _rewardsMinOracles) external;\n}\n"
      },
      "contracts/interfaces/IKeeperValidators.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IKeeperRewards} from './IKeeperRewards.sol';\nimport {IKeeperOracles} from './IKeeperOracles.sol';\n\n/**\n * @title IKeeperValidators\n * @author StakeWise\n * @notice Defines the interface for the Keeper validators\n */\ninterface IKeeperValidators is IKeeperOracles, IKeeperRewards {\n  /**\n   * @notice Event emitted on validators approval\n   * @param vault The address of the Vault\n   * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures\n   */\n  event ValidatorsApproval(address indexed vault, string exitSignaturesIpfsHash);\n\n  /**\n   * @notice Event emitted on exit signatures update\n   * @param caller The address of the function caller\n   * @param vault The address of the Vault\n   * @param nonce The nonce used for verifying Oracles' signatures\n   * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures\n   */\n  event ExitSignaturesUpdated(\n    address indexed caller,\n    address indexed vault,\n    uint256 nonce,\n    string exitSignaturesIpfsHash\n  );\n\n  /**\n   * @notice Event emitted on validators min oracles number update\n   * @param oracles The new minimum number of oracles required to approve validators\n   */\n  event ValidatorsMinOraclesUpdated(uint256 oracles);\n\n  /**\n   * @notice Get nonce for the next vault exit signatures update\n   * @param vault The address of the Vault to get the nonce for\n   * @return The nonce of the Vault for updating signatures\n   */\n  function exitSignaturesNonces(address vault) external view returns (uint256);\n\n  /**\n   * @notice Struct for approving registration of one or more validators\n   * @param validatorsRegistryRoot The deposit data root used to verify that oracles approved validators\n   * @param deadline The deadline for submitting the approval\n   * @param validators The concatenation of the validators' public key, signature and deposit data root\n   * @param signatures The concatenation of Oracles' signatures\n   * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures\n   */\n  struct ApprovalParams {\n    bytes32 validatorsRegistryRoot;\n    uint256 deadline;\n    bytes validators;\n    bytes signatures;\n    string exitSignaturesIpfsHash;\n  }\n\n  /**\n   * @notice The minimum number of oracles required to update validators\n   * @return The minimum number of oracles\n   */\n  function validatorsMinOracles() external view returns (uint256);\n\n  /**\n   * @notice Function for approving validators registration\n   * @param params The parameters for approving validators registration\n   */\n  function approveValidators(ApprovalParams calldata params) external;\n\n  /**\n   * @notice Function for updating exit signatures for every hard fork\n   * @param vault The address of the Vault to update signatures for\n   * @param deadline The deadline for submitting signatures update\n   * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures\n   * @param oraclesSignatures The concatenation of Oracles' signatures\n   */\n  function updateExitSignatures(\n    address vault,\n    uint256 deadline,\n    string calldata exitSignaturesIpfsHash,\n    bytes calldata oraclesSignatures\n  ) external;\n\n  /**\n   * @notice Function for updating validators min oracles number\n   * @param _validatorsMinOracles The new minimum number of oracles required to approve validators\n   */\n  function setValidatorsMinOracles(uint256 _validatorsMinOracles) external;\n}\n"
      },
      "contracts/interfaces/IMulticall.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.22;\n\n/**\n * @title Multicall\n * @author Uniswap\n * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol\n * @notice Enables calling multiple methods in a single call to the contract\n */\ninterface IMulticall {\n  /**\n   * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\n   * @param data The encoded function data for each of the calls to make to this contract\n   * @return results The results from each of the calls passed in via data\n   */\n  function multicall(bytes[] calldata data) external returns (bytes[] memory results);\n}\n"
      },
      "contracts/interfaces/IOwnMevEscrow.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\n/**\n * @title IOwnMevEscrow\n * @author StakeWise\n * @notice Defines the interface for the OwnMevEscrow contract\n */\ninterface IOwnMevEscrow {\n  /**\n   * @notice Event emitted on received MEV\n   * @param assets The amount of MEV assets received\n   */\n  event MevReceived(uint256 assets);\n\n  /**\n   * @notice Event emitted on harvest\n   * @param assets The amount of assets withdrawn\n   */\n  event Harvested(uint256 assets);\n\n  /**\n   * @notice Vault address\n   * @return The address of the vault that owns the escrow\n   */\n  function vault() external view returns (address payable);\n\n  /**\n   * @notice Withdraws MEV accumulated in the escrow. Can be called only by the Vault.\n   * @dev IMPORTANT: because control is transferred to the Vault, care must be\n   *    taken to not create reentrancy vulnerabilities. The Vault must follow the checks-effects-interactions pattern:\n   *    https://docs.soliditylang.org/en/v0.8.22/security-considerations.html#use-the-checks-effects-interactions-pattern\n   * @return assets The amount of assets withdrawn\n   */\n  function harvest() external returns (uint256 assets);\n}\n"
      },
      "contracts/interfaces/ISharedMevEscrow.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\n/**\n * @title ISharedMevEscrow\n * @author StakeWise\n * @notice Defines the interface for the SharedMevEscrow contract\n */\ninterface ISharedMevEscrow {\n  /**\n   * @notice Event emitted on received MEV\n   * @param assets The amount of MEV assets received\n   */\n  event MevReceived(uint256 assets);\n\n  /**\n   * @notice Event emitted on harvest\n   * @param caller The function caller\n   * @param assets The amount of assets withdrawn\n   */\n  event Harvested(address indexed caller, uint256 assets);\n\n  /**\n   * @notice Withdraws MEV accumulated in the escrow. Can be called only by the Vault.\n   * @dev IMPORTANT: because control is transferred to the Vault, care must be\n   *    taken to not create reentrancy vulnerabilities. The Vault must follow the checks-effects-interactions pattern:\n   *    https://docs.soliditylang.org/en/v0.8.22/security-considerations.html#use-the-checks-effects-interactions-pattern\n   * @param assets The amount of assets to withdraw\n   */\n  function harvest(uint256 assets) external;\n}\n"
      },
      "contracts/interfaces/IValidatorsRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\n\npragma solidity =0.8.22;\n\n/**\n * @title IValidatorsRegistry\n * @author Ethereum Foundation\n * @notice The validators deposit contract common interface\n */\ninterface IValidatorsRegistry {\n  /// @notice A processed deposit event.\n  event DepositEvent(\n    bytes pubkey,\n    bytes withdrawal_credentials,\n    bytes amount,\n    bytes signature,\n    bytes index\n  );\n\n  /// @notice Query the current deposit root hash.\n  /// @return The deposit root hash.\n  function get_deposit_root() external view returns (bytes32);\n}\n"
      },
      "contracts/interfaces/IVaultAdmin.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\n/**\n * @title IVaultState\n * @author StakeWise\n * @notice Defines the interface for the VaultAdmin contract\n */\ninterface IVaultAdmin {\n  /**\n   * @notice Event emitted on metadata ipfs hash update\n   * @param caller The address of the function caller\n   * @param metadataIpfsHash The new metadata IPFS hash\n   */\n  event MetadataUpdated(address indexed caller, string metadataIpfsHash);\n\n  /**\n   * @notice The Vault admin\n   * @return The address of the Vault admin\n   */\n  function admin() external view returns (address);\n\n  /**\n   * @notice Function for updating the metadata IPFS hash. Can only be called by Vault admin.\n   * @param metadataIpfsHash The new metadata IPFS hash\n   */\n  function setMetadata(string calldata metadataIpfsHash) external;\n}\n"
      },
      "contracts/interfaces/IVaultBlocklist.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultAdmin} from './IVaultAdmin.sol';\n\n/**\n * @title IVaultBlocklist\n * @author StakeWise\n * @notice Defines the interface for the VaultBlocklist contract\n */\ninterface IVaultBlocklist is IVaultAdmin {\n  /**\n   * @notice Event emitted on blocklist update\n   * @param caller The address of the function caller\n   * @param account The address of the account updated\n   * @param isBlocked Whether account is blocked or not\n   */\n  event BlocklistUpdated(address indexed caller, address indexed account, bool isBlocked);\n\n  /**\n   * @notice Event emitted when blocklist manager address is updated\n   * @param caller The address of the function caller\n   * @param blocklistManager The address of the new blocklist manager\n   */\n  event BlocklistManagerUpdated(address indexed caller, address indexed blocklistManager);\n\n  /**\n   * @notice Blocklist manager address\n   * @return The address of the blocklist manager\n   */\n  function blocklistManager() external view returns (address);\n\n  /**\n   * @notice Checks whether account is blocked or not\n   * @param account The account to check\n   * @return `true` for the blocked account, `false` otherwise\n   */\n  function blockedAccounts(address account) external view returns (bool);\n\n  /**\n   * @notice Add or remove account from the blocklist. Can only be called by the blocklist manager.\n   * @param account The account to add or remove to the blocklist\n   * @param isBlocked Whether account should be blocked or not\n   */\n  function updateBlocklist(address account, bool isBlocked) external;\n\n  /**\n   * @notice Used to update the blocklist manager. Can only be called by the Vault admin.\n   * @param _blocklistManager The address of the new blocklist manager\n   */\n  function setBlocklistManager(address _blocklistManager) external;\n}\n"
      },
      "contracts/interfaces/IVaultEnterExit.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultState} from './IVaultState.sol';\n\n/**\n * @title IVaultEnterExit\n * @author StakeWise\n * @notice Defines the interface for the VaultEnterExit contract\n */\ninterface IVaultEnterExit is IVaultState {\n  /**\n   * @notice Event emitted on deposit\n   * @param caller The address that called the deposit function\n   * @param receiver The address that received the shares\n   * @param assets The number of assets deposited by the caller\n   * @param shares The number of shares received\n   * @param referrer The address of the referrer\n   */\n  event Deposited(\n    address indexed caller,\n    address indexed receiver,\n    uint256 assets,\n    uint256 shares,\n    address referrer\n  );\n\n  /**\n   * @notice Event emitted on redeem\n   * @param owner The address that owns the shares\n   * @param receiver The address that received withdrawn assets\n   * @param assets The total number of withdrawn assets\n   * @param shares The total number of withdrawn shares\n   */\n  event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares);\n\n  /**\n   * @notice Event emitted on shares added to the exit queue\n   * @param owner The address that owns the shares\n   * @param receiver The address that will receive withdrawn assets\n   * @param positionTicket The exit queue ticket that was assigned to the position\n   * @param shares The number of shares that queued for the exit\n   */\n  event ExitQueueEntered(\n    address indexed owner,\n    address indexed receiver,\n    uint256 positionTicket,\n    uint256 shares\n  );\n\n  /**\n   * @notice Event emitted on claim of the exited assets\n   * @param receiver The address that has received withdrawn assets\n   * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call\n   * @param newPositionTicket The new exit queue ticket in case not all the shares were withdrawn. Otherwise 0.\n   * @param withdrawnAssets The total number of assets withdrawn\n   */\n  event ExitedAssetsClaimed(\n    address indexed receiver,\n    uint256 prevPositionTicket,\n    uint256 newPositionTicket,\n    uint256 withdrawnAssets\n  );\n\n  /**\n   * @notice Locks shares to the exit queue. The shares continue earning rewards until they will be burned by the Vault.\n   * @param shares The number of shares to lock\n   * @param receiver The address that will receive assets upon withdrawal\n   * @return positionTicket The position ticket of the exit queue\n   */\n  function enterExitQueue(\n    uint256 shares,\n    address receiver\n  ) external returns (uint256 positionTicket);\n\n  /**\n   * @notice Get the exit queue index to claim exited assets from\n   * @param positionTicket The exit queue position ticket to get the index for\n   * @return The exit queue index that should be used to claim exited assets.\n   *         Returns -1 in case such index does not exist.\n   */\n  function getExitQueueIndex(uint256 positionTicket) external view returns (int256);\n\n  /**\n   * @notice Calculates the number of shares and assets that can be claimed from the exit queue.\n   * @param receiver The address that will receive assets upon withdrawal\n   * @param positionTicket The exit queue ticket received after the `enterExitQueue` call\n   * @param timestamp The timestamp when the shares entered the exit queue\n   * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`.\n   * @return leftShares The number of shares that are still in the queue\n   * @return claimedShares The number of claimed shares\n   * @return claimedAssets The number of claimed assets\n   */\n  function calculateExitedAssets(\n    address receiver,\n    uint256 positionTicket,\n    uint256 timestamp,\n    uint256 exitQueueIndex\n  ) external view returns (uint256 leftShares, uint256 claimedShares, uint256 claimedAssets);\n\n  /**\n   * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`.\n   * @param positionTicket The exit queue ticket received after the `enterExitQueue` call\n   * @param timestamp The timestamp when the shares entered the exit queue\n   * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`.\n   * @return newPositionTicket The new exit queue ticket in case not all the shares were burned. Otherwise 0.\n   * @return claimedShares The number of shares claimed\n   * @return claimedAssets The number of assets claimed\n   */\n  function claimExitedAssets(\n    uint256 positionTicket,\n    uint256 timestamp,\n    uint256 exitQueueIndex\n  ) external returns (uint256 newPositionTicket, uint256 claimedShares, uint256 claimedAssets);\n\n  /**\n   * @notice Redeems assets from the Vault by utilising what has not been staked yet. Can only be called when vault is not collateralized.\n   * @param shares The number of shares to burn\n   * @param receiver The address that will receive assets\n   * @return assets The number of assets withdrawn\n   */\n  function redeem(uint256 shares, address receiver) external returns (uint256 assets);\n}\n"
      },
      "contracts/interfaces/IVaultEthStaking.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultState} from './IVaultState.sol';\nimport {IVaultValidators} from './IVaultValidators.sol';\nimport {IVaultEnterExit} from './IVaultEnterExit.sol';\nimport {IKeeperRewards} from './IKeeperRewards.sol';\nimport {IVaultMev} from './IVaultMev.sol';\n\n/**\n * @title IVaultEthStaking\n * @author StakeWise\n * @notice Defines the interface for the VaultEthStaking contract\n */\ninterface IVaultEthStaking is IVaultState, IVaultValidators, IVaultEnterExit, IVaultMev {\n  /**\n   * @notice Deposit ETH to the Vault\n   * @param receiver The address that will receive Vault's shares\n   * @param referrer The address of the referrer. Set to zero address if not used.\n   * @return shares The number of shares minted\n   */\n  function deposit(address receiver, address referrer) external payable returns (uint256 shares);\n\n  /**\n   * @notice Used by MEV escrow to transfer ETH.\n   */\n  function receiveFromMevEscrow() external payable;\n\n  /**\n   * @notice Updates Vault state and deposits ETH to the Vault\n   * @param receiver The address that will receive Vault's shares\n   * @param referrer The address of the referrer. Set to zero address if not used.\n   * @param harvestParams The parameters for harvesting Keeper rewards\n   * @return shares The number of shares minted\n   */\n  function updateStateAndDeposit(\n    address receiver,\n    address referrer,\n    IKeeperRewards.HarvestParams calldata harvestParams\n  ) external payable returns (uint256 shares);\n}\n"
      },
      "contracts/interfaces/IVaultFee.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultAdmin} from './IVaultAdmin.sol';\n\n/**\n * @title IVaultFee\n * @author StakeWise\n * @notice Defines the interface for the VaultFee contract\n */\ninterface IVaultFee is IVaultAdmin {\n  /**\n   * @notice Event emitted on fee recipient update\n   * @param caller The address of the function caller\n   * @param feeRecipient The address of the new fee recipient\n   */\n  event FeeRecipientUpdated(address indexed caller, address indexed feeRecipient);\n\n  /**\n   * @notice The Vault's fee recipient\n   * @return The address of the Vault's fee recipient\n   */\n  function feeRecipient() external view returns (address);\n\n  /**\n   * @notice The Vault's fee percent in BPS\n   * @return The fee percent applied by the Vault on the rewards\n   */\n  function feePercent() external view returns (uint16);\n\n  /**\n   * @notice Function for updating the fee recipient address. Can only be called by the admin.\n   * @param _feeRecipient The address of the new fee recipient\n   */\n  function setFeeRecipient(address _feeRecipient) external;\n}\n"
      },
      "contracts/interfaces/IVaultMev.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultState} from './IVaultState.sol';\n\n/**\n * @title IVaultMev\n * @author StakeWise\n * @notice Common interface for the VaultMev contracts\n */\ninterface IVaultMev is IVaultState {\n  /**\n   * @notice The contract that accumulates MEV rewards\n   * @return The MEV escrow contract address\n   */\n  function mevEscrow() external view returns (address);\n}\n"
      },
      "contracts/interfaces/IVaultOsToken.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IVaultState} from './IVaultState.sol';\nimport {IVaultEnterExit} from './IVaultEnterExit.sol';\n\n/**\n * @title IVaultOsToken\n * @author StakeWise\n * @notice Defines the interface for the VaultOsToken contract\n */\ninterface IVaultOsToken is IVaultState, IVaultEnterExit {\n  /**\n   * @notice Event emitted on minting osToken\n   * @param caller The address of the function caller\n   * @param receiver The address of the osToken receiver\n   * @param assets The amount of minted assets\n   * @param shares The amount of minted shares\n   * @param referrer The address of the referrer\n   */\n  event OsTokenMinted(\n    address indexed caller,\n    address receiver,\n    uint256 assets,\n    uint256 shares,\n    address referrer\n  );\n\n  /**\n   * @notice Event emitted on burning OsToken\n   * @param caller The address of the function caller\n   * @param assets The amount of burned assets\n   * @param shares The amount of burned shares\n   */\n  event OsTokenBurned(address indexed caller, uint256 assets, uint256 shares);\n\n  /**\n   * @notice Event emitted on osToken position liquidation\n   * @param caller The address of the function caller\n   * @param user The address of the user liquidated\n   * @param receiver The address of the receiver of the liquidated assets\n   * @param osTokenShares The amount of osToken shares to liquidate\n   * @param shares The amount of vault shares burned\n   * @param receivedAssets The amount of assets received\n   */\n  event OsTokenLiquidated(\n    address indexed caller,\n    address indexed user,\n    address receiver,\n    uint256 osTokenShares,\n    uint256 shares,\n    uint256 receivedAssets\n  );\n\n  /**\n   * @notice Event emitted on osToken position redemption\n   * @param caller The address of the function caller\n   * @param user The address of the position owner to redeem from\n   * @param receiver The address of the receiver of the redeemed assets\n   * @param osTokenShares The amount of osToken shares to redeem\n   * @param shares The amount of vault shares burned\n   * @param assets The amount of assets received\n   */\n  event OsTokenRedeemed(\n    address indexed caller,\n    address indexed user,\n    address receiver,\n    uint256 osTokenShares,\n    uint256 shares,\n    uint256 assets\n  );\n\n  /**\n   * @notice Struct of osToken position\n   * @param shares The total number of minted osToken shares. Will increase based on the treasury fee.\n   * @param cumulativeFeePerShare The cumulative fee per share\n   */\n  struct OsTokenPosition {\n    uint128 shares;\n    uint128 cumulativeFeePerShare;\n  }\n\n  /**\n   * @notice Get total amount of minted osToken shares\n   * @param user The address of the user\n   * @return shares The number of minted osToken shares\n   */\n  function osTokenPositions(address user) external view returns (uint128 shares);\n\n  /**\n   * @notice Mints OsToken shares\n   * @param receiver The address that will receive the minted OsToken shares\n   * @param osTokenShares The number of OsToken shares to mint to the receiver\n   * @param referrer The address of the referrer\n   * @return assets The number of assets minted to the receiver\n   */\n  function mintOsToken(\n    address receiver,\n    uint256 osTokenShares,\n    address referrer\n  ) external returns (uint256 assets);\n\n  /**\n   * @notice Burns osToken shares\n   * @param osTokenShares The number of shares to burn\n   * @return assets The number of assets burned\n   */\n  function burnOsToken(uint128 osTokenShares) external returns (uint256 assets);\n\n  /**\n   * @notice Liquidates a user position and returns the number of received assets.\n   *         Can only be called when health factor is below 1.\n   * @param osTokenShares The number of shares to cover\n   * @param owner The address of the position owner to liquidate\n   * @param receiver The address of the receiver of the liquidated assets\n   */\n  function liquidateOsToken(uint256 osTokenShares, address owner, address receiver) external;\n\n  /**\n   * @notice Redeems osToken shares for assets. Can only be called when health factor is above redeemFromHealthFactor.\n   * @param osTokenShares The number of osToken shares to redeem\n   * @param owner The address of the position owner to redeem from\n   * @param receiver The address of the receiver of the redeemed assets\n   */\n  function redeemOsToken(uint256 osTokenShares, address owner, address receiver) external;\n}\n"
      },
      "contracts/interfaces/IVaultsRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\n/**\n * @title IVaultsRegistry\n * @author StakeWise\n * @notice Defines the interface for the VaultsRegistry\n */\ninterface IVaultsRegistry {\n  /**\n   * @notice Event emitted on a Vault addition\n   * @param caller The address that has added the Vault\n   * @param vault The address of the added Vault\n   */\n  event VaultAdded(address indexed caller, address indexed vault);\n\n  /**\n   * @notice Event emitted on adding Vault implementation contract\n   * @param impl The address of the new implementation contract\n   */\n  event VaultImplAdded(address indexed impl);\n\n  /**\n   * @notice Event emitted on removing Vault implementation contract\n   * @param impl The address of the removed implementation contract\n   */\n  event VaultImplRemoved(address indexed impl);\n\n  /**\n   * @notice Event emitted on whitelisting the factory\n   * @param factory The address of the whitelisted factory\n   */\n  event FactoryAdded(address indexed factory);\n\n  /**\n   * @notice Event emitted on removing the factory from the whitelist\n   * @param factory The address of the factory removed from the whitelist\n   */\n  event FactoryRemoved(address indexed factory);\n\n  /**\n   * @notice Registered Vaults\n   * @param vault The address of the vault to check whether it is registered\n   * @return `true` for the registered Vault, `false` otherwise\n   */\n  function vaults(address vault) external view returns (bool);\n\n  /**\n   * @notice Registered Vault implementations\n   * @param impl The address of the vault implementation\n   * @return `true` for the registered implementation, `false` otherwise\n   */\n  function vaultImpls(address impl) external view returns (bool);\n\n  /**\n   * @notice Registered Factories\n   * @param factory The address of the factory to check whether it is whitelisted\n   * @return `true` for the whitelisted Factory, `false` otherwise\n   */\n  function factories(address factory) external view returns (bool);\n\n  /**\n   * @notice Function for adding Vault to the registry. Can only be called by the whitelisted Factory.\n   * @param vault The address of the Vault to add\n   */\n  function addVault(address vault) external;\n\n  /**\n   * @notice Function for adding Vault implementation contract\n   * @param newImpl The address of the new implementation contract\n   */\n  function addVaultImpl(address newImpl) external;\n\n  /**\n   * @notice Function for removing Vault implementation contract\n   * @param impl The address of the removed implementation contract\n   */\n  function removeVaultImpl(address impl) external;\n\n  /**\n   * @notice Function for adding the factory to the whitelist\n   * @param factory The address of the factory to add to the whitelist\n   */\n  function addFactory(address factory) external;\n\n  /**\n   * @notice Function for removing the factory from the whitelist\n   * @param factory The address of the factory to remove from the whitelist\n   */\n  function removeFactory(address factory) external;\n\n  /**\n   * @notice Function for initializing the registry. Can only be called once during the deployment.\n   * @param _owner The address of the owner of the contract\n   */\n  function initialize(address _owner) external;\n}\n"
      },
      "contracts/interfaces/IVaultState.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IKeeperRewards} from './IKeeperRewards.sol';\nimport {IVaultFee} from './IVaultFee.sol';\n\n/**\n * @title IVaultState\n * @author StakeWise\n * @notice Defines the interface for the VaultState contract\n */\ninterface IVaultState is IVaultFee {\n  /**\n   * @notice Event emitted on checkpoint creation\n   * @param shares The number of burned shares\n   * @param assets The amount of exited assets\n   */\n  event CheckpointCreated(uint256 shares, uint256 assets);\n\n  /**\n   * @notice Event emitted on minting fee recipient shares\n   * @param receiver The address of the fee recipient\n   * @param shares The number of minted shares\n   * @param assets The amount of minted assets\n   */\n  event FeeSharesMinted(address receiver, uint256 shares, uint256 assets);\n\n  /**\n   * @notice Total assets in the Vault\n   * @return The total amount of the underlying asset that is \"managed\" by Vault\n   */\n  function totalAssets() external view returns (uint256);\n\n  /**\n   * @notice Function for retrieving total shares\n   * @return The amount of shares in existence\n   */\n  function totalShares() external view returns (uint256);\n\n  /**\n   * @notice The Vault's capacity\n   * @return The amount after which the Vault stops accepting deposits\n   */\n  function capacity() external view returns (uint256);\n\n  /**\n   * @notice Total assets available in the Vault. They can be staked or withdrawn.\n   * @return The total amount of withdrawable assets\n   */\n  function withdrawableAssets() external view returns (uint256);\n\n  /**\n   * @notice Queued Shares\n   * @return The total number of shares queued for exit\n   */\n  function queuedShares() external view returns (uint128);\n\n  /**\n   * @notice Returns the number of shares held by an account\n   * @param account The account for which to look up the number of shares it has, i.e. its balance\n   * @return The number of shares held by the account\n   */\n  function getShares(address account) external view returns (uint256);\n\n  /**\n   * @notice Converts shares to assets\n   * @param assets The amount of assets to convert to shares\n   * @return shares The amount of shares that the Vault would exchange for the amount of assets provided\n   */\n  function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n  /**\n   * @notice Converts assets to shares\n   * @param shares The amount of shares to convert to assets\n   * @return assets The amount of assets that the Vault would exchange for the amount of shares provided\n   */\n  function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n  /**\n   * @notice Check whether state update is required\n   * @return `true` if state update is required, `false` otherwise\n   */\n  function isStateUpdateRequired() external view returns (bool);\n\n  /**\n   * @notice Updates the total amount of assets in the Vault and its exit queue\n   * @param harvestParams The parameters for harvesting Keeper rewards\n   */\n  function updateState(IKeeperRewards.HarvestParams calldata harvestParams) external;\n}\n"
      },
      "contracts/interfaces/IVaultValidators.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IKeeperValidators} from './IKeeperValidators.sol';\nimport {IVaultAdmin} from './IVaultAdmin.sol';\nimport {IVaultState} from './IVaultState.sol';\n\n/**\n * @title IVaultValidators\n * @author StakeWise\n * @notice Defines the interface for VaultValidators contract\n */\ninterface IVaultValidators is IVaultAdmin, IVaultState {\n  /**\n   * @notice Event emitted on validator registration\n   * @param publicKey The public key of the validator that was registered\n   */\n  event ValidatorRegistered(bytes publicKey);\n\n  /**\n   * @notice Event emitted on keys manager address update\n   * @param caller The address of the function caller\n   * @param keysManager The address of the new keys manager\n   */\n  event KeysManagerUpdated(address indexed caller, address indexed keysManager);\n\n  /**\n   * @notice Event emitted on validators merkle tree root update\n   * @param caller The address of the function caller\n   * @param validatorsRoot The new validators merkle tree root\n   */\n  event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot);\n\n  /**\n   * @notice The Vault keys manager address\n   * @return The address that can update validators merkle tree root\n   */\n  function keysManager() external view returns (address);\n\n  /**\n   * @notice The Vault validators root\n   * @return The merkle tree root to use for verifying validators deposit data\n   */\n  function validatorsRoot() external view returns (bytes32);\n\n  /**\n   * @notice The Vault validator index\n   * @return The index of the next validator to be registered in the current deposit data file\n   */\n  function validatorIndex() external view returns (uint256);\n\n  /**\n   * @notice Function for registering single validator\n   * @param keeperParams The parameters for getting approval from Keeper oracles\n   * @param proof The proof used to verify that the validator is part of the validators merkle tree\n   */\n  function registerValidator(\n    IKeeperValidators.ApprovalParams calldata keeperParams,\n    bytes32[] calldata proof\n  ) external;\n\n  /**\n   * @notice Function for registering multiple validators\n   * @param keeperParams The parameters for getting approval from Keeper oracles\n   * @param indexes The indexes of the leaves for the merkle tree multi proof verification\n   * @param proofFlags The multi proof flags for the merkle tree verification\n   * @param proof The proof used for the merkle tree verification\n   */\n  function registerValidators(\n    IKeeperValidators.ApprovalParams calldata keeperParams,\n    uint256[] calldata indexes,\n    bool[] calldata proofFlags,\n    bytes32[] calldata proof\n  ) external;\n\n  /**\n   * @notice Function for updating the keys manager. Can only be called by the admin.\n   * @param _keysManager The new keys manager address\n   */\n  function setKeysManager(address _keysManager) external;\n\n  /**\n   * @notice Function for updating the validators merkle tree root. Can only be called by the keys manager.\n   * @param _validatorsRoot The new validators merkle tree root\n   */\n  function setValidatorsRoot(bytes32 _validatorsRoot) external;\n}\n"
      },
      "contracts/interfaces/IVaultVersion.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IERC1822Proxiable} from '@openzeppelin/contracts/interfaces/draft-IERC1822.sol';\nimport {IVaultAdmin} from './IVaultAdmin.sol';\n\n/**\n * @title IVaultVersion\n * @author StakeWise\n * @notice Defines the interface for VaultVersion contract\n */\ninterface IVaultVersion is IERC1822Proxiable, IVaultAdmin {\n  /**\n   * @notice Vault Unique Identifier\n   * @return The unique identifier of the Vault\n   */\n  function vaultId() external pure returns (bytes32);\n\n  /**\n   * @notice Version\n   * @return The version of the Vault implementation contract\n   */\n  function version() external pure returns (uint8);\n\n  /**\n   * @notice Implementation\n   * @return The address of the Vault implementation contract\n   */\n  function implementation() external view returns (address);\n}\n"
      },
      "contracts/libraries/Errors.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\n/**\n * @title Errors\n * @author StakeWise\n * @notice Contains all the custom errors\n */\nlibrary Errors {\n  error AccessDenied();\n  error InvalidShares();\n  error InvalidAssets();\n  error ZeroAddress();\n  error InsufficientAssets();\n  error CapacityExceeded();\n  error InvalidCapacity();\n  error InvalidSecurityDeposit();\n  error InvalidFeeRecipient();\n  error InvalidFeePercent();\n  error NotHarvested();\n  error NotCollateralized();\n  error Collateralized();\n  error InvalidProof();\n  error LowLtv();\n  error RedemptionExceeded();\n  error InvalidPosition();\n  error InvalidLtv();\n  error InvalidHealthFactor();\n  error InvalidReceivedAssets();\n  error InvalidTokenMeta();\n  error UpgradeFailed();\n  error InvalidValidator();\n  error InvalidValidators();\n  error WhitelistAlreadyUpdated();\n  error DeadlineExpired();\n  error PermitInvalidSigner();\n  error InvalidValidatorsRegistryRoot();\n  error InvalidVault();\n  error AlreadyAdded();\n  error AlreadyRemoved();\n  error InvalidOracles();\n  error NotEnoughSignatures();\n  error InvalidOracle();\n  error TooEarlyUpdate();\n  error InvalidAvgRewardPerSecond();\n  error InvalidRewardsRoot();\n  error HarvestFailed();\n  error InvalidRedeemFromLtvPercent();\n  error InvalidLiqThresholdPercent();\n  error InvalidLiqBonusPercent();\n  error InvalidLtvPercent();\n  error InvalidCheckpointIndex();\n  error InvalidCheckpointValue();\n  error MaxOraclesExceeded();\n  error ClaimTooEarly();\n}\n"
      },
      "contracts/libraries/ExitQueue.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Math} from '@openzeppelin/contracts/utils/math/Math.sol';\nimport {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol';\nimport {Errors} from './Errors.sol';\n\n/**\n * @title ExitQueue\n * @author StakeWise\n * @notice ExitQueue represent checkpoints of burned shares and exited assets\n */\nlibrary ExitQueue {\n  /**\n   * @notice A struct containing checkpoint data\n   * @param totalTickets The cumulative number of tickets (shares) exited\n   * @param exitedAssets The number of assets that exited in this checkpoint\n   */\n  struct Checkpoint {\n    uint160 totalTickets;\n    uint96 exitedAssets;\n  }\n\n  /**\n   * @notice A struct containing the history of checkpoints data\n   * @param checkpoints An array of checkpoints\n   */\n  struct History {\n    Checkpoint[] checkpoints;\n  }\n\n  /**\n   * @notice Get the latest checkpoint total tickets\n   * @param self An array containing checkpoints\n   * @return The current total tickets or zero if there are no checkpoints\n   */\n  function getLatestTotalTickets(History storage self) internal view returns (uint256) {\n    uint256 pos = self.checkpoints.length;\n    unchecked {\n      // cannot underflow as subtraction happens in case pos > 0\n      return pos == 0 ? 0 : _unsafeAccess(self.checkpoints, pos - 1).totalTickets;\n    }\n  }\n\n  /**\n   * @notice Get checkpoint index for the burned shares\n   * @param self An array containing checkpoints\n   * @param positionTicket The position ticket to search the closest checkpoint for\n   * @return The checkpoint index or the length of checkpoints array in case there is no such\n   */\n  function getCheckpointIndex(\n    History storage self,\n    uint256 positionTicket\n  ) internal view returns (uint256) {\n    uint256 high = self.checkpoints.length;\n    uint256 low;\n    while (low < high) {\n      uint256 mid = Math.average(low, high);\n      if (_unsafeAccess(self.checkpoints, mid).totalTickets > positionTicket) {\n        high = mid;\n      } else {\n        unchecked {\n          // cannot underflow as mid < high\n          low = mid + 1;\n        }\n      }\n    }\n    return high;\n  }\n\n  /**\n   * @notice Calculates burned shares and exited assets\n   * @param self An array containing checkpoints\n   * @param checkpointIdx The index of the checkpoint to start calculating from\n   * @param positionTicket The position ticket to start calculating exited assets from\n   * @param positionShares The number of shares to calculate assets for\n   * @return burnedShares The number of shares burned\n   * @return exitedAssets The number of assets exited\n   */\n  function calculateExitedAssets(\n    History storage self,\n    uint256 checkpointIdx,\n    uint256 positionTicket,\n    uint256 positionShares\n  ) internal view returns (uint256 burnedShares, uint256 exitedAssets) {\n    uint256 length = self.checkpoints.length;\n    // there are no exited assets for such checkpoint index or no shares to burn\n    if (checkpointIdx >= length || positionShares == 0) return (0, 0);\n\n    // previous total tickets for calculating how much shares were burned for the period\n    uint256 prevTotalTickets;\n    unchecked {\n      // cannot underflow as subtraction happens in case checkpointIdx > 0\n      prevTotalTickets = checkpointIdx == 0\n        ? 0\n        : _unsafeAccess(self.checkpoints, checkpointIdx - 1).totalTickets;\n    }\n\n    // current total tickets for calculating assets per burned share\n    // can be used with _unsafeAccess as checkpointIdx < length\n    Checkpoint memory checkpoint = _unsafeAccess(self.checkpoints, checkpointIdx);\n    uint256 currTotalTickets = checkpoint.totalTickets;\n    uint256 checkpointAssets = checkpoint.exitedAssets;\n    // check whether position ticket is in [prevTotalTickets, currTotalTickets) range\n    if (positionTicket < prevTotalTickets || currTotalTickets <= positionTicket) {\n      revert Errors.InvalidCheckpointIndex();\n    }\n\n    // calculate amount of available shares that will be updated while iterating over checkpoints\n    uint256 availableShares;\n    unchecked {\n      // cannot underflow as positionTicket < currTotalTickets\n      availableShares = currTotalTickets - positionTicket;\n    }\n\n    // accumulate assets until the number of required shares is collected\n    uint256 checkpointShares;\n    uint256 sharesDelta;\n    while (true) {\n      unchecked {\n        // cannot underflow as prevTotalTickets <= positionTicket\n        checkpointShares = currTotalTickets - prevTotalTickets;\n        // cannot underflow as positionShares > burnedShares while in the loop\n        sharesDelta = Math.min(availableShares, positionShares - burnedShares);\n\n        // cannot overflow as it is capped with underlying asset total supply\n        burnedShares += sharesDelta;\n        exitedAssets += Math.mulDiv(sharesDelta, checkpointAssets, checkpointShares);\n\n        // cannot overflow as checkpoints are created max once per day\n        checkpointIdx++;\n      }\n\n      // stop when required shares collected or reached end of checkpoints list\n      if (positionShares <= burnedShares || checkpointIdx >= length) {\n        return (burnedShares, exitedAssets);\n      }\n\n      // take next checkpoint\n      prevTotalTickets = currTotalTickets;\n      // can use _unsafeAccess as checkpointIdx < length is checked above\n      checkpoint = _unsafeAccess(self.checkpoints, checkpointIdx);\n      currTotalTickets = checkpoint.totalTickets;\n      checkpointAssets = checkpoint.exitedAssets;\n\n      unchecked {\n        // cannot underflow as every next checkpoint total tickets is larger than previous\n        availableShares = currTotalTickets - prevTotalTickets;\n      }\n    }\n  }\n\n  /**\n   * @notice Pushes a new checkpoint onto a History\n   * @param self An array containing checkpoints\n   * @param shares The number of shares to add to the latest checkpoint\n   * @param assets The number of assets that were exited for this checkpoint\n   */\n  function push(History storage self, uint256 shares, uint256 assets) internal {\n    if (shares == 0 || assets == 0) revert Errors.InvalidCheckpointValue();\n    Checkpoint memory checkpoint = Checkpoint({\n      totalTickets: SafeCast.toUint160(getLatestTotalTickets(self) + shares),\n      exitedAssets: SafeCast.toUint96(assets)\n    });\n    self.checkpoints.push(checkpoint);\n  }\n\n  function _unsafeAccess(\n    Checkpoint[] storage self,\n    uint256 pos\n  ) private pure returns (Checkpoint storage result) {\n    assembly {\n      mstore(0, self.slot)\n      result.slot := add(keccak256(0, 0x20), pos)\n    }\n  }\n}\n"
      },
      "contracts/vaults/ethereum/custom/EthFoxVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {IEthFoxVault} from '../../../interfaces/IEthFoxVault.sol';\nimport {Multicall} from '../../../base/Multicall.sol';\nimport {VaultValidators} from '../../modules/VaultValidators.sol';\nimport {VaultAdmin} from '../../modules/VaultAdmin.sol';\nimport {VaultFee} from '../../modules/VaultFee.sol';\nimport {VaultVersion, IVaultVersion} from '../../modules/VaultVersion.sol';\nimport {VaultImmutables} from '../../modules/VaultImmutables.sol';\nimport {VaultState} from '../../modules/VaultState.sol';\nimport {VaultEnterExit} from '../../modules/VaultEnterExit.sol';\nimport {VaultEthStaking, IVaultEthStaking} from '../../modules/VaultEthStaking.sol';\nimport {VaultMev} from '../../modules/VaultMev.sol';\nimport {VaultBlocklist} from '../../modules/VaultBlocklist.sol';\n\n/**\n * @title EthFoxVault\n * @author StakeWise\n * @notice Custom Ethereum non-ERC20 vault with blocklist, own MEV and without osToken minting.\n */\ncontract EthFoxVault is\n  VaultImmutables,\n  Initializable,\n  VaultAdmin,\n  VaultVersion,\n  VaultFee,\n  VaultState,\n  VaultValidators,\n  VaultEnterExit,\n  VaultMev,\n  VaultEthStaking,\n  VaultBlocklist,\n  Multicall,\n  IEthFoxVault\n{\n  /**\n   * @dev Constructor\n   * @dev Since the immutable variable value is stored in the bytecode,\n   *      its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage.\n   * @param _keeper The address of the Keeper contract\n   * @param _vaultsRegistry The address of the VaultsRegistry contract\n   * @param _validatorsRegistry The contract address used for registering validators in beacon chain\n   * @param sharedMevEscrow The address of the shared MEV escrow\n   * @param exitedAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking\n   */\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor(\n    address _keeper,\n    address _vaultsRegistry,\n    address _validatorsRegistry,\n    address sharedMevEscrow,\n    uint256 exitedAssetsClaimDelay\n  )\n    VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry)\n    VaultEnterExit(exitedAssetsClaimDelay)\n    VaultMev(sharedMevEscrow)\n  {\n    _disableInitializers();\n  }\n\n  /// @inheritdoc IEthFoxVault\n  function initialize(bytes calldata params) external payable virtual override initializer {\n    EthFoxVaultInitParams memory initParams = abi.decode(params, (EthFoxVaultInitParams));\n    __EthFoxVault_init(initParams);\n    emit EthFoxVaultCreated(\n      initParams.admin,\n      initParams.ownMevEscrow,\n      initParams.capacity,\n      initParams.feePercent,\n      initParams.metadataIpfsHash\n    );\n  }\n\n  /// @inheritdoc IVaultEthStaking\n  function deposit(\n    address receiver,\n    address referrer\n  ) public payable virtual override(IVaultEthStaking, VaultEthStaking) returns (uint256 shares) {\n    _checkBlocklist(msg.sender);\n    _checkBlocklist(receiver);\n    return super.deposit(receiver, referrer);\n  }\n\n  /// @inheritdoc IEthFoxVault\n  function ejectUser(address user) external override {\n    // add user to blocklist\n    updateBlocklist(user, true);\n\n    // fetch shares of the user\n    uint256 userShares = _balances[user];\n    if (userShares == 0) return;\n\n    if (_isCollateralized()) {\n      // send user shares to exit queue\n      _enterExitQueue(user, userShares, user);\n    } else {\n      // redeem user shares\n      _redeem(user, userShares, user);\n    }\n    emit UserEjected(user, userShares);\n  }\n\n  /**\n   * @dev Function for depositing using fallback function\n   */\n  receive() external payable virtual override {\n    _checkBlocklist(msg.sender);\n    _deposit(msg.sender, msg.value, address(0));\n  }\n\n  /// @inheritdoc VaultVersion\n  function vaultId() public pure virtual override(IVaultVersion, VaultVersion) returns (bytes32) {\n    return keccak256('EthFoxVault');\n  }\n\n  /// @inheritdoc IVaultVersion\n  function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) {\n    return 1;\n  }\n\n  /**\n   * @dev Initializes the EthFoxVault contract\n   * @param params The decoded parameters for initializing the EthFoxVault contract\n   */\n  function __EthFoxVault_init(EthFoxVaultInitParams memory params) internal onlyInitializing {\n    __VaultAdmin_init(params.admin, params.metadataIpfsHash);\n    // fee recipient is initially set to admin address\n    __VaultFee_init(params.admin, params.feePercent);\n    __VaultState_init(params.capacity);\n    __VaultValidators_init();\n    __VaultMev_init(params.ownMevEscrow);\n    // blocklist manager is initially set to admin address\n    __VaultBlocklist_init(params.admin);\n    __VaultEthStaking_init();\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultAdmin.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {IVaultAdmin} from '../../interfaces/IVaultAdmin.sol';\nimport {Errors} from '../../libraries/Errors.sol';\n\n/**\n * @title VaultAdmin\n * @author StakeWise\n * @notice Defines the admin functionality for the Vault\n */\nabstract contract VaultAdmin is Initializable, IVaultAdmin {\n  /// @inheritdoc IVaultAdmin\n  address public override admin;\n\n  /// @inheritdoc IVaultAdmin\n  function setMetadata(string calldata metadataIpfsHash) external override {\n    _checkAdmin();\n    emit MetadataUpdated(msg.sender, metadataIpfsHash);\n  }\n\n  /**\n   * @dev Initializes the VaultAdmin contract\n   * @param _admin The address of the Vault admin\n   */\n  function __VaultAdmin_init(\n    address _admin,\n    string memory metadataIpfsHash\n  ) internal onlyInitializing {\n    admin = _admin;\n    emit MetadataUpdated(msg.sender, metadataIpfsHash);\n  }\n\n  /**\n   * @dev Internal method for checking whether the caller is admin\n   */\n  function _checkAdmin() internal view {\n    if (msg.sender != admin) revert Errors.AccessDenied();\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultBlocklist.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {IVaultBlocklist} from '../../interfaces/IVaultBlocklist.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultAdmin} from './VaultAdmin.sol';\n\n/**\n * @title VaultBlocklist\n * @author StakeWise\n * @notice Defines the functionality for blocking addresses for the Vault\n */\nabstract contract VaultBlocklist is Initializable, VaultAdmin, IVaultBlocklist {\n  /// @inheritdoc IVaultBlocklist\n  address public override blocklistManager;\n\n  /// @inheritdoc IVaultBlocklist\n  mapping(address => bool) public override blockedAccounts;\n\n  /// @inheritdoc IVaultBlocklist\n  function updateBlocklist(address account, bool isBlocked) public virtual override {\n    if (msg.sender != blocklistManager) revert Errors.AccessDenied();\n    if (blockedAccounts[account] == isBlocked) return;\n\n    blockedAccounts[account] = isBlocked;\n    emit BlocklistUpdated(msg.sender, account, isBlocked);\n  }\n\n  /// @inheritdoc IVaultBlocklist\n  function setBlocklistManager(address _blocklistManager) external override {\n    _checkAdmin();\n    _setBlocklistManager(_blocklistManager);\n  }\n\n  /**\n   * @notice Internal function for checking blocklist\n   * @param account The address of the account to check\n   */\n  function _checkBlocklist(address account) internal view {\n    if (blockedAccounts[account]) revert Errors.AccessDenied();\n  }\n\n  /**\n   * @dev Internal function for updating the blocklist manager externally or from the initializer\n   * @param _blocklistManager The address of the new blocklist manager\n   */\n  function _setBlocklistManager(address _blocklistManager) private {\n    // update blocklist manager address\n    blocklistManager = _blocklistManager;\n    emit BlocklistManagerUpdated(msg.sender, _blocklistManager);\n  }\n\n  /**\n   * @dev Initializes the VaultBlocklist contract\n   * @param _blocklistManager The address of the blocklist manager\n   */\n  function __VaultBlocklist_init(address _blocklistManager) internal onlyInitializing {\n    _setBlocklistManager(_blocklistManager);\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultEnterExit.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol';\nimport {Math} from '@openzeppelin/contracts/utils/math/Math.sol';\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {IVaultEnterExit} from '../../interfaces/IVaultEnterExit.sol';\nimport {ExitQueue} from '../../libraries/ExitQueue.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultImmutables} from './VaultImmutables.sol';\nimport {VaultState} from './VaultState.sol';\n\n/**\n * @title VaultEnterExit\n * @author StakeWise\n * @notice Defines the functionality for entering and exiting the Vault\n */\nabstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, IVaultEnterExit {\n  using ExitQueue for ExitQueue.History;\n\n  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n  uint256 private immutable _exitingAssetsClaimDelay;\n\n  /**\n   * @dev Constructor\n   * @dev Since the immutable variable value is stored in the bytecode,\n   *      its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage.\n   * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue\n   */\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor(uint256 exitingAssetsClaimDelay) {\n    _exitingAssetsClaimDelay = exitingAssetsClaimDelay;\n  }\n\n  /// @inheritdoc IVaultEnterExit\n  function getExitQueueIndex(uint256 positionTicket) external view override returns (int256) {\n    uint256 checkpointIdx = _exitQueue.getCheckpointIndex(positionTicket);\n    return checkpointIdx < _exitQueue.checkpoints.length ? int256(checkpointIdx) : -1;\n  }\n\n  /// @inheritdoc IVaultEnterExit\n  function redeem(\n    uint256 shares,\n    address receiver\n  ) public virtual override returns (uint256 assets) {\n    return _redeem(msg.sender, shares, receiver);\n  }\n\n  /// @inheritdoc IVaultEnterExit\n  function enterExitQueue(\n    uint256 shares,\n    address receiver\n  ) public virtual override returns (uint256 positionTicket) {\n    return _enterExitQueue(msg.sender, shares, receiver);\n  }\n\n  /// @inheritdoc IVaultEnterExit\n  function calculateExitedAssets(\n    address receiver,\n    uint256 positionTicket,\n    uint256 timestamp,\n    uint256 exitQueueIndex\n  )\n    public\n    view\n    override\n    returns (uint256 leftShares, uint256 claimedShares, uint256 claimedAssets)\n  {\n    uint256 requestedShares = _exitRequests[\n      keccak256(abi.encode(receiver, timestamp, positionTicket))\n    ];\n\n    // calculate exited shares and assets\n    (claimedShares, claimedAssets) = _exitQueue.calculateExitedAssets(\n      exitQueueIndex,\n      positionTicket,\n      requestedShares\n    );\n    leftShares = requestedShares - claimedShares;\n  }\n\n  /// @inheritdoc IVaultEnterExit\n  function claimExitedAssets(\n    uint256 positionTicket,\n    uint256 timestamp,\n    uint256 exitQueueIndex\n  )\n    external\n    override\n    returns (uint256 newPositionTicket, uint256 claimedShares, uint256 claimedAssets)\n  {\n    if (block.timestamp < timestamp + _exitingAssetsClaimDelay) revert Errors.ClaimTooEarly();\n    bytes32 queueId = keccak256(abi.encode(msg.sender, timestamp, positionTicket));\n\n    // calculate exited shares and assets\n    uint256 leftShares;\n    (leftShares, claimedShares, claimedAssets) = calculateExitedAssets(\n      msg.sender,\n      positionTicket,\n      timestamp,\n      exitQueueIndex\n    );\n    // nothing to claim\n    if (claimedShares == 0) return (positionTicket, claimedShares, claimedAssets);\n\n    // clean up current exit request\n    delete _exitRequests[queueId];\n\n    // skip creating new position for the shares rounding error\n    if (leftShares > 1) {\n      // update user's queue position\n      newPositionTicket = positionTicket + claimedShares;\n      _exitRequests[keccak256(abi.encode(msg.sender, timestamp, newPositionTicket))] = leftShares;\n    }\n\n    // transfer assets to the receiver\n    _unclaimedAssets -= SafeCast.toUint128(claimedAssets);\n    _transferVaultAssets(msg.sender, claimedAssets);\n    emit ExitedAssetsClaimed(msg.sender, positionTicket, newPositionTicket, claimedAssets);\n  }\n\n  /**\n   * @dev Internal function that must be used to process user deposits\n   * @param to The address to mint shares to\n   * @param assets The number of assets deposited\n   * @param referrer The address of the referrer. Set to zero address if not used.\n   * @return shares The total amount of shares minted\n   */\n  function _deposit(\n    address to,\n    uint256 assets,\n    address referrer\n  ) internal virtual returns (uint256 shares) {\n    _checkHarvested();\n    if (to == address(0)) revert Errors.ZeroAddress();\n    if (assets == 0) revert Errors.InvalidAssets();\n\n    uint256 totalAssetsAfter;\n    unchecked {\n      // cannot overflow as it is capped with underlying asset total supply\n      totalAssetsAfter = _totalAssets + assets;\n    }\n    if (totalAssetsAfter > capacity()) revert Errors.CapacityExceeded();\n\n    // calculate amount of shares to mint\n    shares = _convertToShares(assets, Math.Rounding.Ceil);\n\n    // update state\n    _totalAssets = SafeCast.toUint128(totalAssetsAfter);\n    _mintShares(to, shares);\n\n    emit Deposited(msg.sender, to, assets, shares, referrer);\n  }\n\n  /**\n   * @dev Internal function that must be used to process user withdrawals before first validator registration\n   * @param user The address of the user\n   * @param shares The number of shares to redeem\n   * @param receiver The address that will receive the assets\n   * @return assets The total amount of assets withdrawn\n   */\n  function _redeem(\n    address user,\n    uint256 shares,\n    address receiver\n  ) internal returns (uint256 assets) {\n    _checkNotCollateralized();\n    if (shares == 0) revert Errors.InvalidShares();\n    if (receiver == address(0)) revert Errors.ZeroAddress();\n\n    // calculate amount of assets to burn\n    assets = convertToAssets(shares);\n    if (assets == 0) revert Errors.InvalidAssets();\n\n    // reverts in case there are not enough withdrawable assets\n    if (assets > withdrawableAssets()) revert Errors.InsufficientAssets();\n\n    // update total assets\n    _totalAssets -= SafeCast.toUint128(assets);\n\n    // burn owner shares\n    _burnShares(user, shares);\n\n    // transfer assets to the receiver\n    _transferVaultAssets(receiver, assets);\n\n    emit Redeemed(user, receiver, assets, shares);\n  }\n\n  /**\n   * @dev Internal function that must be used to process user withdrawals after first validator registration\n   * @param user The address of the user\n   * @param shares The number of shares to send to exit queue\n   * @param receiver The address that will receive the assets\n   * @return positionTicket The position ticket in the exit queue\n   */\n  function _enterExitQueue(\n    address user,\n    uint256 shares,\n    address receiver\n  ) internal virtual returns (uint256 positionTicket) {\n    _checkCollateralized();\n    if (shares == 0) revert Errors.InvalidShares();\n    if (receiver == address(0)) revert Errors.ZeroAddress();\n\n    // SLOAD to memory\n    uint256 _queuedShares = queuedShares;\n\n    // calculate position ticket\n    positionTicket = _exitQueue.getLatestTotalTickets() + _queuedShares;\n\n    // add to the exit requests\n    _exitRequests[keccak256(abi.encode(receiver, block.timestamp, positionTicket))] = shares;\n\n    // reverts if owner does not have enough shares\n    _balances[user] -= shares;\n\n    unchecked {\n      // cannot overflow as it is capped with _totalShares\n      queuedShares = SafeCast.toUint128(_queuedShares + shares);\n    }\n\n    emit ExitQueueEntered(user, receiver, positionTicket, shares);\n  }\n\n  /**\n   * @dev Internal function for transferring assets from the Vault to the receiver\n   * @dev IMPORTANT: because control is transferred to the receiver, care must be\n   *    taken to not create reentrancy vulnerabilities. The Vault must follow the checks-effects-interactions pattern:\n   *    https://docs.soliditylang.org/en/v0.8.22/security-considerations.html#use-the-checks-effects-interactions-pattern\n   * @param receiver The address that will receive the assets\n   * @param assets The number of assets to transfer\n   */\n  function _transferVaultAssets(address receiver, uint256 assets) internal virtual;\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultEthStaking.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {ReentrancyGuardUpgradeable} from '@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol';\nimport {Address} from '@openzeppelin/contracts/utils/Address.sol';\nimport {IEthValidatorsRegistry} from '../../interfaces/IEthValidatorsRegistry.sol';\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {IVaultEthStaking} from '../../interfaces/IVaultEthStaking.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultValidators} from './VaultValidators.sol';\nimport {VaultState} from './VaultState.sol';\nimport {VaultEnterExit} from './VaultEnterExit.sol';\nimport {VaultMev} from './VaultMev.sol';\n\n/**\n * @title VaultEthStaking\n * @author StakeWise\n * @notice Defines the Ethereum staking functionality for the Vault\n */\nabstract contract VaultEthStaking is\n  Initializable,\n  ReentrancyGuardUpgradeable,\n  VaultState,\n  VaultValidators,\n  VaultEnterExit,\n  VaultMev,\n  IVaultEthStaking\n{\n  uint256 private constant _securityDeposit = 1e9;\n\n  /// @inheritdoc IVaultEthStaking\n  function deposit(\n    address receiver,\n    address referrer\n  ) public payable virtual override returns (uint256 shares) {\n    return _deposit(receiver, msg.value, referrer);\n  }\n\n  /// @inheritdoc IVaultEthStaking\n  function updateStateAndDeposit(\n    address receiver,\n    address referrer,\n    IKeeperRewards.HarvestParams calldata harvestParams\n  ) public payable virtual override returns (uint256 shares) {\n    updateState(harvestParams);\n    return deposit(receiver, referrer);\n  }\n\n  /**\n   * @dev Function for depositing using fallback function\n   */\n  receive() external payable virtual {\n    _deposit(msg.sender, msg.value, address(0));\n  }\n\n  /// @inheritdoc IVaultEthStaking\n  function receiveFromMevEscrow() external payable override {\n    if (msg.sender != mevEscrow()) revert Errors.AccessDenied();\n  }\n\n  /// @inheritdoc VaultValidators\n  function _registerSingleValidator(bytes calldata validator) internal virtual override {\n    bytes calldata publicKey = validator[:48];\n    IEthValidatorsRegistry(_validatorsRegistry).deposit{value: _validatorDeposit()}(\n      publicKey,\n      _withdrawalCredentials(),\n      validator[48:144],\n      bytes32(validator[144:_validatorLength])\n    );\n\n    emit ValidatorRegistered(publicKey);\n  }\n\n  /// @inheritdoc VaultValidators\n  function _registerMultipleValidators(\n    bytes calldata validators,\n    uint256[] calldata indexes\n  ) internal virtual override returns (bytes32[] memory leaves) {\n    // SLOAD to memory\n    uint256 currentValIndex = validatorIndex;\n\n    uint256 startIndex;\n    uint256 endIndex;\n    bytes calldata validator;\n    bytes calldata publicKey;\n    uint256 validatorsCount = indexes.length;\n    leaves = new bytes32[](validatorsCount);\n    uint256 validatorDeposit = _validatorDeposit();\n    bytes memory withdrawalCreds = _withdrawalCredentials();\n\n    for (uint256 i = 0; i < validatorsCount; i++) {\n      unchecked {\n        // cannot realistically overflow\n        endIndex += _validatorLength;\n      }\n      validator = validators[startIndex:endIndex];\n      leaves[indexes[i]] = keccak256(\n        bytes.concat(keccak256(abi.encode(validator, currentValIndex)))\n      );\n      publicKey = validator[:48];\n      // slither-disable-next-line arbitrary-send-eth\n      IEthValidatorsRegistry(_validatorsRegistry).deposit{value: validatorDeposit}(\n        publicKey,\n        withdrawalCreds,\n        validator[48:144],\n        bytes32(validator[144:_validatorLength])\n      );\n      startIndex = endIndex;\n      unchecked {\n        // cannot realistically overflow\n        ++currentValIndex;\n      }\n      emit ValidatorRegistered(publicKey);\n    }\n  }\n\n  /// @inheritdoc VaultState\n  function _vaultAssets() internal view virtual override returns (uint256) {\n    return address(this).balance;\n  }\n\n  /// @inheritdoc VaultEnterExit\n  function _transferVaultAssets(\n    address receiver,\n    uint256 assets\n  ) internal virtual override nonReentrant {\n    return Address.sendValue(payable(receiver), assets);\n  }\n\n  /// @inheritdoc VaultValidators\n  function _validatorDeposit() internal pure override returns (uint256) {\n    return 32 ether;\n  }\n\n  /**\n   * @dev Initializes the VaultEthStaking contract\n   */\n  function __VaultEthStaking_init() internal onlyInitializing {\n    __ReentrancyGuard_init();\n\n    // see https://github.com/OpenZeppelin/openzeppelin-contracts/issues/3706\n    if (msg.value < _securityDeposit) revert Errors.InvalidSecurityDeposit();\n    _deposit(address(this), msg.value, address(0));\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultFee.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {IVaultFee} from '../../interfaces/IVaultFee.sol';\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultAdmin} from './VaultAdmin.sol';\nimport {VaultImmutables} from './VaultImmutables.sol';\n\n/**\n * @title VaultFee\n * @author StakeWise\n * @notice Defines the fee functionality for the Vault\n */\nabstract contract VaultFee is VaultImmutables, Initializable, VaultAdmin, IVaultFee {\n  uint256 internal constant _maxFeePercent = 10_000; // @dev 100.00 %\n\n  /// @inheritdoc IVaultFee\n  address public override feeRecipient;\n\n  /// @inheritdoc IVaultFee\n  uint16 public override feePercent;\n\n  /// @inheritdoc IVaultFee\n  function setFeeRecipient(address _feeRecipient) external override {\n    _checkAdmin();\n    _setFeeRecipient(_feeRecipient);\n  }\n\n  /**\n   * @dev Internal function for updating the fee recipient externally or from the initializer\n   * @param _feeRecipient The address of the new fee recipient\n   */\n  function _setFeeRecipient(address _feeRecipient) private {\n    _checkHarvested();\n    if (_feeRecipient == address(0)) revert Errors.InvalidFeeRecipient();\n\n    // update fee recipient address\n    feeRecipient = _feeRecipient;\n    emit FeeRecipientUpdated(msg.sender, _feeRecipient);\n  }\n\n  /**\n   * @dev Initializes the VaultFee contract\n   * @param _feeRecipient The address of the fee recipient\n   * @param _feePercent The fee percent that is charged by the Vault\n   */\n  function __VaultFee_init(address _feeRecipient, uint16 _feePercent) internal onlyInitializing {\n    if (_feePercent > _maxFeePercent) revert Errors.InvalidFeePercent();\n\n    _setFeeRecipient(_feeRecipient);\n    feePercent = _feePercent;\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultImmutables.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {Errors} from '../../libraries/Errors.sol';\n\n/**\n * @title VaultImmutables\n * @author StakeWise\n * @notice Defines the Vault common immutable variables\n */\nabstract contract VaultImmutables {\n  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n  address internal immutable _keeper;\n\n  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n  address internal immutable _vaultsRegistry;\n\n  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n  address internal immutable _validatorsRegistry;\n\n  /**\n   * @dev Constructor\n   * @dev Since the immutable variable value is stored in the bytecode,\n   *      its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage.\n   * @param keeper The address of the Keeper contract\n   * @param vaultsRegistry The address of the VaultsRegistry contract\n   * @param validatorsRegistry The contract address used for registering validators in beacon chain\n   */\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor(address keeper, address vaultsRegistry, address validatorsRegistry) {\n    _keeper = keeper;\n    _vaultsRegistry = vaultsRegistry;\n    _validatorsRegistry = validatorsRegistry;\n  }\n\n  /**\n   * @dev Internal method for checking whether the vault is collateralized\n   * @return true if the vault is collateralized, false otherwise\n   */\n  function _isCollateralized() internal view returns (bool) {\n    return IKeeperRewards(_keeper).isCollateralized(address(this));\n  }\n\n  /**\n   * @dev Internal method for checking whether the vault is harvested\n   */\n  function _checkHarvested() internal view {\n    if (IKeeperRewards(_keeper).isHarvestRequired(address(this))) revert Errors.NotHarvested();\n  }\n\n  /**\n   * @dev Internal method for checking whether the vault is collateralized\n   */\n  function _checkCollateralized() internal view {\n    if (!_isCollateralized()) revert Errors.NotCollateralized();\n  }\n\n  /**\n   * @dev Internal method for checking whether the vault is not collateralized\n   */\n  function _checkNotCollateralized() internal view {\n    if (_isCollateralized()) revert Errors.Collateralized();\n  }\n}\n"
      },
      "contracts/vaults/modules/VaultMev.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {ISharedMevEscrow} from '../../interfaces/ISharedMevEscrow.sol';\nimport {IOwnMevEscrow} from '../../interfaces/IOwnMevEscrow.sol';\nimport {IVaultMev} from '../../interfaces/IVaultMev.sol';\nimport {VaultState} from './VaultState.sol';\n\n/**\n * @title VaultMev\n * @author StakeWise\n * @notice Defines the Vaults' MEV functionality\n */\nabstract contract VaultMev is Initializable, VaultState, IVaultMev {\n  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n  address private immutable _sharedMevEscrow;\n  address private _ownMevEscrow;\n\n  /**\n   * @dev Constructor\n   * @dev Since the immutable variable value is stored in the bytecode,\n   *      its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage.\n   * @param sharedMevEscrow The address of the shared MEV escrow\n   */\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor(address sharedMevEscrow) {\n    _sharedMevEscrow = sharedMevEscrow;\n  }\n\n  /// @inheritdoc IVaultMev\n  function mevEscrow() public view override returns (address) {\n    // SLOAD to memory\n    address ownMevEscrow = _ownMevEscrow;\n    return ownMevEscrow != address(0) ? ownMevEscrow : _sharedMevEscrow;\n  }\n\n  /// @inheritdoc VaultState\n  function _harvestAssets(\n    IKeeperRewards.HarvestParams calldata harvestParams\n  ) internal override returns (int256, bool) {\n    (int256 totalAssetsDelta, uint256 unlockedMevDelta, bool harvested) = IKeeperRewards(_keeper)\n      .harvest(harvestParams);\n\n    // harvest execution rewards only when consensus rewards were harvested\n    if (!harvested) return (totalAssetsDelta, harvested);\n\n    // SLOAD to memory\n    address _mevEscrow = mevEscrow();\n    if (_mevEscrow == _sharedMevEscrow) {\n      if (unlockedMevDelta > 0) {\n        // withdraw assets from shared escrow only in case reward is positive\n        ISharedMevEscrow(_mevEscrow).harvest(unlockedMevDelta);\n      }\n      return (totalAssetsDelta, harvested);\n    }\n\n    // execution rewards are always equal to what was accumulated in own MEV escrow\n    return (totalAssetsDelta + int256(IOwnMevEscrow(_mevEscrow).harvest()), harvested);\n  }\n\n  /**\n   * @dev Initializes the VaultMev contract\n   * @param ownMevEscrow The address of the own MEV escrow contract\n   */\n  function __VaultMev_init(address ownMevEscrow) internal onlyInitializing {\n    if (ownMevEscrow != address(0)) _ownMevEscrow = ownMevEscrow;\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultState.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol';\nimport {Math} from '@openzeppelin/contracts/utils/math/Math.sol';\nimport {IVaultState} from '../../interfaces/IVaultState.sol';\nimport {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol';\nimport {ExitQueue} from '../../libraries/ExitQueue.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultImmutables} from './VaultImmutables.sol';\nimport {VaultFee} from './VaultFee.sol';\n\n/**\n * @title VaultState\n * @author StakeWise\n * @notice Defines Vault's state manipulation\n */\nabstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVaultState {\n  using ExitQueue for ExitQueue.History;\n\n  uint128 internal _totalShares;\n  uint128 internal _totalAssets;\n\n  /// @inheritdoc IVaultState\n  uint128 public override queuedShares;\n  uint128 internal _unclaimedAssets;\n\n  ExitQueue.History internal _exitQueue;\n  mapping(bytes32 => uint256) internal _exitRequests;\n  mapping(address => uint256) internal _balances;\n\n  uint256 private _capacity;\n\n  /// @inheritdoc IVaultState\n  function totalShares() external view override returns (uint256) {\n    return _totalShares;\n  }\n\n  /// @inheritdoc IVaultState\n  function totalAssets() external view override returns (uint256) {\n    return _totalAssets;\n  }\n\n  /// @inheritdoc IVaultState\n  function getShares(address account) external view override returns (uint256) {\n    return _balances[account];\n  }\n\n  /// @inheritdoc IVaultState\n  function convertToShares(uint256 assets) public view override returns (uint256 shares) {\n    return _convertToShares(assets, Math.Rounding.Floor);\n  }\n\n  /// @inheritdoc IVaultState\n  function convertToAssets(uint256 shares) public view override returns (uint256 assets) {\n    uint256 totalShares_ = _totalShares;\n    return (totalShares_ == 0) ? shares : Math.mulDiv(shares, _totalAssets, totalShares_);\n  }\n\n  /// @inheritdoc IVaultState\n  function capacity() public view override returns (uint256) {\n    // SLOAD to memory\n    uint256 capacity_ = _capacity;\n\n    // if capacity is not set, it is unlimited\n    return capacity_ == 0 ? type(uint256).max : capacity_;\n  }\n\n  /// @inheritdoc IVaultState\n  function withdrawableAssets() public view override returns (uint256) {\n    uint256 vaultAssets = _vaultAssets();\n    unchecked {\n      // calculate assets that are reserved by users who queued for exit\n      // cannot overflow as it is capped with underlying asset total supply\n      uint256 reservedAssets = convertToAssets(queuedShares) + _unclaimedAssets;\n      return vaultAssets > reservedAssets ? vaultAssets - reservedAssets : 0;\n    }\n  }\n\n  /// @inheritdoc IVaultState\n  function isStateUpdateRequired() external view override returns (bool) {\n    return IKeeperRewards(_keeper).isHarvestRequired(address(this));\n  }\n\n  /// @inheritdoc IVaultState\n  function updateState(\n    IKeeperRewards.HarvestParams calldata harvestParams\n  ) public virtual override {\n    // process total assets delta  since last update\n    (int256 totalAssetsDelta, bool harvested) = _harvestAssets(harvestParams);\n\n    // process total assets delta if it has changed\n    if (totalAssetsDelta != 0) _processTotalAssetsDelta(totalAssetsDelta);\n\n    // update exit queue every time new update is harvested\n    if (harvested) _updateExitQueue();\n  }\n\n  /**\n   * @dev Internal function for processing rewards and penalties\n   * @param totalAssetsDelta The number of assets earned or lost\n   */\n  function _processTotalAssetsDelta(int256 totalAssetsDelta) internal {\n    // SLOAD to memory\n    uint256 newTotalAssets = _totalAssets;\n    if (totalAssetsDelta < 0) {\n      // add penalty to total assets\n      newTotalAssets -= uint256(-totalAssetsDelta);\n\n      // update state\n      _totalAssets = SafeCast.toUint128(newTotalAssets);\n      return;\n    }\n\n    // convert assets delta as it is positive\n    uint256 profitAssets = uint256(totalAssetsDelta);\n    newTotalAssets += profitAssets;\n\n    // update state\n    _totalAssets = SafeCast.toUint128(newTotalAssets);\n\n    // calculate admin fee recipient assets\n    uint256 feeRecipientAssets = Math.mulDiv(profitAssets, feePercent, _maxFeePercent);\n    if (feeRecipientAssets == 0) return;\n\n    // SLOAD to memory\n    uint256 totalShares_ = _totalShares;\n\n    // calculate fee recipient's shares\n    uint256 feeRecipientShares;\n    if (totalShares_ == 0) {\n      feeRecipientShares = feeRecipientAssets;\n    } else {\n      unchecked {\n        feeRecipientShares = Math.mulDiv(\n          feeRecipientAssets,\n          totalShares_,\n          newTotalAssets - feeRecipientAssets\n        );\n      }\n    }\n\n    // SLOAD to memory\n    address _feeRecipient = feeRecipient;\n    // mint shares to the fee recipient\n    _mintShares(_feeRecipient, feeRecipientShares);\n    emit FeeSharesMinted(_feeRecipient, feeRecipientShares, feeRecipientAssets);\n  }\n\n  /**\n\t * @dev Internal function that must be used to process exit queue\n   * @dev Make sure that sufficient time passed between exit queue updates (at least 1 day).\n          Currently it's restricted by the keeper's harvest interval\n   * @return burnedShares The total amount of burned shares\n   */\n  function _updateExitQueue() internal virtual returns (uint256 burnedShares) {\n    // SLOAD to memory\n    uint256 _queuedShares = queuedShares;\n    if (_queuedShares == 0) return 0;\n\n    // calculate the amount of assets that can be exited\n    uint256 unclaimedAssets = _unclaimedAssets;\n    uint256 exitedAssets = Math.min(\n      _vaultAssets() - unclaimedAssets,\n      convertToAssets(_queuedShares)\n    );\n    if (exitedAssets == 0) return 0;\n\n    // calculate the amount of shares that can be burned\n    burnedShares = convertToShares(exitedAssets);\n    if (burnedShares == 0) return 0;\n\n    // update queued shares and unclaimed assets\n    queuedShares = SafeCast.toUint128(_queuedShares - burnedShares);\n    _unclaimedAssets = SafeCast.toUint128(unclaimedAssets + exitedAssets);\n\n    // push checkpoint so that exited assets could be claimed\n    _exitQueue.push(burnedShares, exitedAssets);\n    emit CheckpointCreated(burnedShares, exitedAssets);\n\n    // update state\n    _totalShares -= SafeCast.toUint128(burnedShares);\n    _totalAssets -= SafeCast.toUint128(exitedAssets);\n  }\n\n  /**\n   * @dev Internal function for minting shares\n   * @param owner The address of the owner to mint shares to\n   * @param shares The number of shares to mint\n   */\n  function _mintShares(address owner, uint256 shares) internal virtual {\n    // update total shares\n    _totalShares += SafeCast.toUint128(shares);\n\n    // mint shares\n    unchecked {\n      // cannot overflow because the sum of all user\n      // balances can't exceed the max uint256 value\n      _balances[owner] += shares;\n    }\n  }\n\n  /**\n   * @dev Internal function for burning shares\n   * @param owner The address of the owner to burn shares for\n   * @param shares The number of shares to burn\n   */\n  function _burnShares(address owner, uint256 shares) internal virtual {\n    // burn shares\n    _balances[owner] -= shares;\n\n    // update total shares\n    unchecked {\n      // cannot underflow because the sum of all shares can't exceed the _totalShares\n      _totalShares -= SafeCast.toUint128(shares);\n    }\n  }\n\n  /**\n   * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n   */\n  function _convertToShares(\n    uint256 assets,\n    Math.Rounding rounding\n  ) internal view returns (uint256 shares) {\n    uint256 totalShares_ = _totalShares;\n    // Will revert if assets > 0, totalShares > 0 and _totalAssets = 0.\n    // That corresponds to a case where any asset would represent an infinite amount of shares.\n    return\n      (assets == 0 || totalShares_ == 0)\n        ? assets\n        : Math.mulDiv(assets, totalShares_, _totalAssets, rounding);\n  }\n\n  /**\n   * @dev Internal function for harvesting Vaults' new assets\n   * @return The total assets delta after harvest\n   * @return `true` when the rewards were harvested, `false` otherwise\n   */\n  function _harvestAssets(\n    IKeeperRewards.HarvestParams calldata harvestParams\n  ) internal virtual returns (int256, bool);\n\n  /**\n\t * @dev Internal function for retrieving the total assets stored in the Vault.\n          NB! Assets can be forcibly sent to the vault, the returned value must be used with caution\n   * @return The total amount of assets stored in the Vault\n   */\n  function _vaultAssets() internal view virtual returns (uint256);\n\n  /**\n   * @dev Initializes the VaultState contract\n   * @param capacity_ The amount after which the Vault stops accepting deposits\n   */\n  function __VaultState_init(uint256 capacity_) internal onlyInitializing {\n    if (capacity_ == 0) revert Errors.InvalidCapacity();\n    // skip setting capacity if it is unlimited\n    if (capacity_ != type(uint256).max) _capacity = capacity_;\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultValidators.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {MerkleProof} from '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol';\nimport {IKeeperValidators} from '../../interfaces/IKeeperValidators.sol';\nimport {IVaultValidators} from '../../interfaces/IVaultValidators.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultImmutables} from './VaultImmutables.sol';\nimport {VaultAdmin} from './VaultAdmin.sol';\nimport {VaultState} from './VaultState.sol';\n\n/**\n * @title VaultValidators\n * @author StakeWise\n * @notice Defines the validators functionality for the Vault\n */\nabstract contract VaultValidators is\n  VaultImmutables,\n  Initializable,\n  VaultAdmin,\n  VaultState,\n  IVaultValidators\n{\n  uint256 internal constant _validatorLength = 176;\n\n  /// @inheritdoc IVaultValidators\n  bytes32 public override validatorsRoot;\n\n  /// @inheritdoc IVaultValidators\n  uint256 public override validatorIndex;\n\n  address private _keysManager;\n\n  /// @inheritdoc IVaultValidators\n  function keysManager() public view override returns (address) {\n    // SLOAD to memory\n    address keysManager_ = _keysManager;\n    // if keysManager is not set, use admin address\n    return keysManager_ == address(0) ? admin : keysManager_;\n  }\n\n  /// @inheritdoc IVaultValidators\n  function registerValidator(\n    IKeeperValidators.ApprovalParams calldata keeperParams,\n    bytes32[] calldata proof\n  ) external override {\n    _checkHarvested();\n\n    // get approval from oracles\n    IKeeperValidators(_keeper).approveValidators(keeperParams);\n\n    // check enough withdrawable assets\n    if (withdrawableAssets() < _validatorDeposit()) revert Errors.InsufficientAssets();\n\n    // check validator length is valid\n    if (keeperParams.validators.length != _validatorLength) revert Errors.InvalidValidator();\n\n    // SLOAD to memory\n    uint256 currentIndex = validatorIndex;\n\n    // check matches merkle root and next validator index\n    if (\n      !MerkleProof.verifyCalldata(\n        proof,\n        validatorsRoot,\n        keccak256(bytes.concat(keccak256(abi.encode(keeperParams.validators, currentIndex))))\n      )\n    ) {\n      revert Errors.InvalidProof();\n    }\n\n    // register validator\n    _registerSingleValidator(keeperParams.validators);\n\n    // increment index for the next validator\n    unchecked {\n      // cannot realistically overflow\n      validatorIndex = currentIndex + 1;\n    }\n  }\n\n  /// @inheritdoc IVaultValidators\n  function registerValidators(\n    IKeeperValidators.ApprovalParams calldata keeperParams,\n    uint256[] calldata indexes,\n    bool[] calldata proofFlags,\n    bytes32[] calldata proof\n  ) external override {\n    _checkHarvested();\n\n    // get approval from oracles\n    IKeeperValidators(_keeper).approveValidators(keeperParams);\n\n    // check enough withdrawable assets\n    uint256 validatorsCount = indexes.length;\n    if (withdrawableAssets() < _validatorDeposit() * validatorsCount) {\n      revert Errors.InsufficientAssets();\n    }\n\n    // check validators length is valid\n    unchecked {\n      if (\n        validatorsCount == 0 || validatorsCount * _validatorLength != keeperParams.validators.length\n      ) {\n        revert Errors.InvalidValidators();\n      }\n    }\n\n    // check matches merkle root and next validator index\n    if (\n      !MerkleProof.multiProofVerifyCalldata(\n        proof,\n        proofFlags,\n        validatorsRoot,\n        _registerMultipleValidators(keeperParams.validators, indexes)\n      )\n    ) {\n      revert Errors.InvalidProof();\n    }\n\n    // increment index for the next validator\n    unchecked {\n      // cannot realistically overflow\n      validatorIndex += validatorsCount;\n    }\n  }\n\n  /// @inheritdoc IVaultValidators\n  function setKeysManager(address keysManager_) external override {\n    _checkAdmin();\n    if (keysManager_ == address(0)) revert Errors.ZeroAddress();\n    // update keysManager address\n    _keysManager = keysManager_;\n    emit KeysManagerUpdated(msg.sender, keysManager_);\n  }\n\n  /// @inheritdoc IVaultValidators\n  function setValidatorsRoot(bytes32 _validatorsRoot) external override {\n    if (msg.sender != keysManager()) revert Errors.AccessDenied();\n    _setValidatorsRoot(_validatorsRoot);\n  }\n\n  /**\n   * @dev Internal function for updating the validators root externally or from the initializer\n   * @param _validatorsRoot The new validators merkle tree root\n   */\n  function _setValidatorsRoot(bytes32 _validatorsRoot) private {\n    validatorsRoot = _validatorsRoot;\n    // reset validator index on every root update\n    validatorIndex = 0;\n    emit ValidatorsRootUpdated(msg.sender, _validatorsRoot);\n  }\n\n  /**\n   * @dev Internal function for calculating Vault withdrawal credentials\n   * @return The credentials used for the validators withdrawals\n   */\n  function _withdrawalCredentials() internal view returns (bytes memory) {\n    return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this));\n  }\n\n  /**\n   * @dev Internal function for registering single validator. Must emit ValidatorRegistered event.\n   * @param validator The concatenation of the validator public key, signature and deposit data root\n   */\n  function _registerSingleValidator(bytes calldata validator) internal virtual;\n\n  /**\n   * @dev Internal function for registering multiple validators. Must emit ValidatorRegistered event for every validator.\n   * @param validators The concatenation of the validators' public key, signature and deposit data root\n   * @param indexes The indexes of the leaves for the merkle tree multi proof verification\n   * @return leaves The leaves used for the merkle tree multi proof verification\n   */\n  function _registerMultipleValidators(\n    bytes calldata validators,\n    uint256[] calldata indexes\n  ) internal virtual returns (bytes32[] memory leaves);\n\n  /**\n   * @dev Internal function for fetching validator deposit amount\n   */\n  function _validatorDeposit() internal pure virtual returns (uint256);\n\n  /**\n   * @dev Initializes the VaultValidators contract\n   * @dev NB! This initializer must be called after VaultState initializer\n   */\n  function __VaultValidators_init() internal view onlyInitializing {\n    if (capacity() < _validatorDeposit()) revert Errors.InvalidCapacity();\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/vaults/modules/VaultVersion.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.22;\n\nimport {UUPSUpgradeable} from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';\nimport {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport {ERC1967Utils} from '@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol';\nimport {IVaultsRegistry} from '../../interfaces/IVaultsRegistry.sol';\nimport {IVaultVersion} from '../../interfaces/IVaultVersion.sol';\nimport {Errors} from '../../libraries/Errors.sol';\nimport {VaultAdmin} from './VaultAdmin.sol';\nimport {VaultImmutables} from './VaultImmutables.sol';\n\n/**\n * @title VaultVersion\n * @author StakeWise\n * @notice Defines the versioning functionality for the Vault\n */\nabstract contract VaultVersion is\n  VaultImmutables,\n  Initializable,\n  UUPSUpgradeable,\n  VaultAdmin,\n  IVaultVersion\n{\n  bytes4 private constant _initSelector = bytes4(keccak256('initialize(bytes)'));\n\n  /// @inheritdoc IVaultVersion\n  function implementation() external view override returns (address) {\n    return ERC1967Utils.getImplementation();\n  }\n\n  /// @inheritdoc UUPSUpgradeable\n  function upgradeToAndCall(\n    address newImplementation,\n    bytes memory data\n  ) public payable override onlyProxy {\n    super.upgradeToAndCall(newImplementation, abi.encodeWithSelector(_initSelector, data));\n  }\n\n  /// @inheritdoc UUPSUpgradeable\n  function _authorizeUpgrade(address newImplementation) internal view override {\n    _checkAdmin();\n    if (\n      newImplementation == address(0) ||\n      ERC1967Utils.getImplementation() == newImplementation || // cannot reinit the same implementation\n      IVaultVersion(newImplementation).vaultId() != vaultId() || // vault must be of the same type\n      IVaultVersion(newImplementation).version() != version() + 1 || // vault cannot skip versions between\n      !IVaultsRegistry(_vaultsRegistry).vaultImpls(newImplementation) // new implementation must be registered\n    ) {\n      revert Errors.UpgradeFailed();\n    }\n  }\n\n  /// @inheritdoc IVaultVersion\n  function vaultId() public pure virtual override returns (bytes32);\n\n  /// @inheritdoc IVaultVersion\n  function version() public pure virtual override returns (uint8);\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      }
    },
    "settings": {
      "viaIR": true,
      "optimizer": {
        "enabled": true,
        "runs": 200,
        "details": {
          "yul": true
        }
      },
      "evmVersion": "shanghai",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}