{
  "_format": "hh3-sol-build-info-1",
  "id": "solc-0_8_33-8a8197f199e47567790c3b9e32470a2af3dca8ea",
  "solcVersion": "0.8.33",
  "solcLongVersion": "0.8.33+commit.64118f21",
  "userSourceNameMap": {
    "contracts/allocate/DirectAllocation.sol": "project/contracts/allocate/DirectAllocation.sol",
    "contracts/allocate/IssuanceAllocator.sol": "project/contracts/allocate/IssuanceAllocator.sol",
    "contracts/common/BaseUpgradeable.sol": "project/contracts/common/BaseUpgradeable.sol",
    "contracts/common/IGraphToken.sol": "project/contracts/common/IGraphToken.sol",
    "contracts/eligibility/RewardsEligibilityOracle.sol": "project/contracts/eligibility/RewardsEligibilityOracle.sol",
    "contracts/test/allocate/IssuanceAllocatorTestHarness.sol": "project/contracts/test/allocate/IssuanceAllocatorTestHarness.sol",
    "contracts/test/allocate/MockERC165.sol": "project/contracts/test/allocate/MockERC165.sol",
    "contracts/test/allocate/MockNotificationTracker.sol": "project/contracts/test/allocate/MockNotificationTracker.sol",
    "contracts/test/allocate/MockReentrantTarget.sol": "project/contracts/test/allocate/MockReentrantTarget.sol",
    "contracts/test/allocate/MockRevertingTarget.sol": "project/contracts/test/allocate/MockRevertingTarget.sol",
    "contracts/test/allocate/MockSimpleTarget.sol": "project/contracts/test/allocate/MockSimpleTarget.sol"
  },
  "input": {
    "language": "Solidity",
    "settings": {
      "evmVersion": "cancun",
      "optimizer": {
        "enabled": true,
        "runs": 100
      },
      "outputSelection": {
        "*": {
          "": [
            "ast"
          ],
          "*": [
            "abi",
            "evm.bytecode",
            "evm.deployedBytecode",
            "evm.methodIdentifiers",
            "metadata"
          ]
        }
      },
      "remappings": [
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@graphprotocol/interfaces/=npm/@graphprotocol/interfaces@local/",
        "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/",
        "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/",
        "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/",
        "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/",
        "project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/",
        "project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/"
      ],
      "viaIR": true
    },
    "sources": {
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceAllocationAdministration.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\nimport { IIssuanceTarget } from \"./IIssuanceTarget.sol\";\nimport { SelfMintingEventMode } from \"./IIssuanceAllocatorTypes.sol\";\n\n/**\n * @title IIssuanceAllocationAdministration\n * @author Edge & Node\n * @notice Interface for administrative operations on the issuance allocator.\n * These functions are typically restricted to the governor role.\n */\ninterface IIssuanceAllocationAdministration {\n    /**\n     * @notice Set the issuance per block.\n     * @param newIssuancePerBlock New issuance per block\n     * @return applied True if the value is applied (including if already the case)\n     * @dev Requires distribution to have reached block.number\n     */\n    function setIssuancePerBlock(uint256 newIssuancePerBlock) external returns (bool applied);\n\n    /**\n     * @notice Set the issuance per block, requiring distribution has reached at least the specified block\n     * @param newIssuancePerBlock New issuance per block\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return applied True if the value is applied (including if already the case), false if distribution hasn't reached minDistributedBlock\n     * @dev Governance should explicitly call\n     * distributePendingIssuance(blockNumber) first if distribution is behind minDistributedBlock.\n     * @dev This allows configuration changes while paused: first call distributePendingIssuance(blockNumber),\n     * then call this function with the same or lower blockNumber.\n     */\n    function setIssuancePerBlock(\n        uint256 newIssuancePerBlock,\n        uint256 minDistributedBlock\n    ) external returns (bool applied);\n\n    /**\n     * @notice Set the allocation for a target with only allocator minting\n     * @param target The target contract to update\n     * @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)\n     * @return applied True if the value is applied (including if already the case), false if not applied\n     * @dev This variant sets selfMintingRate to 0 and evenIfDistributionPending to false\n     */\n    function setTargetAllocation(IIssuanceTarget target, uint256 allocatorMintingRate) external returns (bool applied);\n\n    /**\n     * @notice Set the allocation for a target with both allocator and self minting\n     * @param target The target contract to update\n     * @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate Self-minting rate for the target (tokens per block)\n     * @return applied True if the value is applied (including if already the case), false if not applied\n     * @dev This variant sets evenIfDistributionPending to false\n     */\n    function setTargetAllocation(\n        IIssuanceTarget target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate\n    ) external returns (bool applied);\n\n    /**\n     * @notice Set the allocation for a target, provided distribution has reached at least the specified block\n     * @param target The target contract to update\n     * @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate Self-minting rate for the target (tokens per block)\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return applied True if the value is applied (including if already the case), false if distribution hasn't reached minDistributedBlock and therefore the change was not applied\n     * @dev Governance should explicitly call\n     * distributePendingIssuance(blockNumber) first if paused and not distributed up to minDistributedBlock block.\n     * @dev This allows configuration changes while paused: first call distributePendingIssuance(blockNumber),\n     * then call this function with the same or lower blockNumber.\n     */\n    function setTargetAllocation(\n        IIssuanceTarget target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate,\n        uint256 minDistributedBlock\n    ) external returns (bool applied);\n\n    /**\n     * @notice Notify a specific target about an upcoming allocation change\n     * @param target Address of the target to notify\n     * @return notified True if notification was sent or already sent this block, false otherwise\n     */\n    function notifyTarget(address target) external returns (bool notified);\n\n    /**\n     * @notice Force set the lastChangeNotifiedBlock for a target to a specific block number\n     * @param target Address of the target to update\n     * @param blockNumber Block number to set as the lastChangeNotifiedBlock\n     * @return notificationBlock The block number that was set\n     * @dev This can be used to enable notification to be sent again (by setting to a past block)\n     * @dev or to prevent notification until a future block (by setting to current or future block).\n     */\n    function forceTargetNoChangeNotificationBlock(\n        address target,\n        uint256 blockNumber\n    ) external returns (uint256 notificationBlock);\n\n    /**\n     * @notice Set the address that receives the default portion of issuance not allocated to other targets\n     * @param newAddress The new default target address (can be address(0))\n     * @return applied True if applied\n     */\n    function setDefaultTarget(address newAddress) external returns (bool applied);\n\n    /**\n     * @notice Set the address that receives the default portion of issuance not allocated to other targets\n     * @param newAddress The new default target address (can be address(0))\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return applied True if applied, false if distribution has not reached minDistributedBlock and therefore the change was not applied\n     * @dev Governance should explicitly call\n     * distributePendingIssuance(blockNumber) first if paused and distribution is not up to minDistributedBlock block.\n     * then call this function with the same or lower blockNumber.\n     */\n    function setDefaultTarget(address newAddress, uint256 minDistributedBlock) external returns (bool applied);\n\n    /**\n     * @notice Distribute pending accumulated allocator-minting issuance\n     * @dev Distributes accumulated allocator-minting issuance using current rates\n     * (retroactively applied to the period from lastDistributionBlock to current block).\n     * Prioritizes non-default targets getting full rates; default gets remainder.\n     * @dev Finalizes self-minting accumulation for the period being distributed.\n     * @return distributedBlock Block number that issuance was distributed up to\n     */\n    function distributePendingIssuance() external returns (uint256 distributedBlock);\n\n    /**\n     * @notice Distribute pending accumulated allocator-minting issuance up to specified block\n     * @param toBlockNumber Block number to distribute up to (must be <= block.number and >= lastDistributionBlock)\n     * @dev Distributes accumulated allocator-minting issuance using current rates\n     * (retroactively applied to the period from lastDistributionBlock to toBlockNumber).\n     * Prioritizes non-default targets getting full rates; default gets remainder.\n     * @dev Finalizes self-minting accumulation for the period being distributed.\n     * @return distributedBlock Block number that issuance was distributed up to\n     */\n    function distributePendingIssuance(uint256 toBlockNumber) external returns (uint256 distributedBlock);\n\n    /**\n     * @notice Set the self-minting event emission mode\n     * @param newMode The new emission mode (None, Aggregate, or PerTarget)\n     * @return applied True if the mode was set (including if already set to that mode)\n     * @dev None: Skip event emission entirely (lowest gas)\n     * @dev Aggregate: Emit single aggregated event for all self-minting (medium gas)\n     * @dev PerTarget: Emit events for each target with self-minting (highest gas)\n     * @dev Self-minting targets should call getTargetIssuancePerBlock() rather than relying on events\n     */\n    function setSelfMintingEventMode(SelfMintingEventMode newMode) external returns (bool applied);\n\n    /**\n     * @notice Get the current self-minting event emission mode\n     * @return mode The current emission mode\n     */\n    function getSelfMintingEventMode() external view returns (SelfMintingEventMode mode);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceAllocationData.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\npragma abicoder v2;\n\nimport { AllocationTarget } from \"./IIssuanceAllocatorTypes.sol\";\n\n/**\n * @title IIssuanceAllocationData\n * @author Edge & Node\n * @notice Interface for querying issuance allocation target data\n * @dev This interface provides access to internal allocation target information,\n * primarily useful for operators and off-chain monitoring systems.\n */\ninterface IIssuanceAllocationData {\n    /**\n     * @notice Get target data for a specific target\n     * @param target Address of the target\n     * @return AllocationTarget struct containing target information including lastChangeNotifiedBlock\n     */\n    function getTargetData(address target) external view returns (AllocationTarget memory);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceAllocationDistribution.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\npragma abicoder v2;\n\nimport { TargetIssuancePerBlock } from \"./IIssuanceAllocatorTypes.sol\";\n\n/**\n * @title IIssuanceAllocationDistribution\n * @author Edge & Node\n * @notice Interface for distribution and target interaction with the issuance allocator.\n * This is the minimal interface that targets need to interact with the allocator.\n */\ninterface IIssuanceAllocationDistribution {\n    /**\n     * @notice Distribute issuance to allocated non-self-minting targets.\n     * @return Block number that issuance has been distributed to. That will normally be the current block number, unless the contract is paused.\n     *\n     * @dev When the contract is paused, no issuance is distributed and lastIssuanceBlock is not updated.\n     * @dev This function is permissionless and can be called by anyone, including targets as part of their normal flow.\n     */\n    function distributeIssuance() external returns (uint256);\n\n    /**\n     * @notice Target issuance per block information\n     * @param target Address of the target\n     * @return targetIssuance TargetIssuancePerBlock struct containing allocatorIssuanceBlockAppliedTo, selfIssuanceBlockAppliedTo, allocatorIssuanceRate, and selfIssuanceRate\n     * @dev This function does not revert when paused, instead the caller is expected to correctly read and apply the information provided.\n     * @dev Targets should check allocatorIssuanceBlockAppliedTo and selfIssuanceBlockAppliedTo - if either is not the current block, that type of issuance is paused for that target.\n     * @dev Targets should not check the allocator's pause state directly, but rely on the blockAppliedTo fields to determine if issuance is paused.\n     */\n    function getTargetIssuancePerBlock(\n        address target\n    ) external view returns (TargetIssuancePerBlock memory targetIssuance);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceAllocationStatus.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\npragma abicoder v2;\n\nimport { Allocation, DistributionState } from \"./IIssuanceAllocatorTypes.sol\";\n\n/**\n * @title IIssuanceAllocationStatus\n * @author Edge & Node\n * @notice Interface for read-only status and query operations on the issuance allocator.\n * All functions in this interface are view functions that provide information about\n * the current state of the allocator, including allocations and system status.\n */\ninterface IIssuanceAllocationStatus {\n    /**\n     * @notice Get the current allocation for a target\n     * @param target Address of the target\n     * @return allocation Allocation struct containing total, allocator-minting, and self-minting allocations\n     */\n    function getTargetAllocation(address target) external view returns (Allocation memory allocation);\n\n    /**\n     * @notice Get the current global allocation totals\n     * @return allocation Allocation struct containing total, allocator-minting, and self-minting allocations across all targets\n     */\n    function getTotalAllocation() external view returns (Allocation memory allocation);\n\n    /**\n     * @notice Get all allocated target addresses\n     * @return targets Array of target addresses\n     */\n    function getTargets() external view returns (address[] memory targets);\n\n    /**\n     * @notice Get a specific allocated target address by index\n     * @param index The index of the target address to retrieve\n     * @return target The target address at the specified index\n     */\n    function getTargetAt(uint256 index) external view returns (address target);\n\n    /**\n     * @notice Get the number of allocated targets\n     * @return count The total number of allocated targets\n     */\n    function getTargetCount() external view returns (uint256 count);\n\n    /**\n     * @notice Get the current issuance per block\n     * @return issuancePerBlock The current issuance per block\n     */\n    function getIssuancePerBlock() external view returns (uint256 issuancePerBlock);\n\n    /**\n     * @notice Get pending issuance distribution state\n     * @return distributionState DistributionState struct containing block tracking and accumulation info\n     */\n    function getDistributionState() external view returns (DistributionState memory distributionState);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceAllocatorTypes.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\npragma abicoder v2;\n\n/**\n * @notice Controls self-minting event emission behavior to manage gas costs\n * @dev None skips event emission entirely (lowest gas)\n * @dev Aggregate emits a single aggregated event for all self-minting\n * @dev PerTarget emits events for each target with self-minting (highest gas)\n */\nenum SelfMintingEventMode {\n    None,\n    Aggregate,\n    PerTarget\n}\n\n/**\n * @notice Target issuance per block information\n * @param allocatorIssuanceRate Issuance rate for allocator-minting (tokens per block)\n * @param allocatorIssuanceBlockAppliedTo The block up to which allocator issuance has been applied\n * @param selfIssuanceRate Issuance rate for self-minting (tokens per block)\n * @param selfIssuanceBlockAppliedTo The block up to which self issuance has been applied\n */\nstruct TargetIssuancePerBlock {\n    uint256 allocatorIssuanceRate;\n    uint256 allocatorIssuanceBlockAppliedTo;\n    uint256 selfIssuanceRate;\n    uint256 selfIssuanceBlockAppliedTo;\n}\n\n/**\n * @notice Allocation information\n * @param totalAllocationRate Total allocation rate (tokens per block: allocatorMintingRate + selfMintingRate)\n * @param allocatorMintingRate Allocator-minting allocation rate (tokens per block)\n * @param selfMintingRate Self-minting allocation rate (tokens per block)\n */\nstruct Allocation {\n    uint256 totalAllocationRate;\n    uint256 allocatorMintingRate;\n    uint256 selfMintingRate;\n}\n\n/**\n * @notice Allocation target information\n * @param allocatorMintingRate The allocator-minting allocation rate (tokens per block)\n * @param selfMintingRate The self-minting allocation rate (tokens per block)\n * @param lastChangeNotifiedBlock Last block when this target was notified of changes\n */\nstruct AllocationTarget {\n    uint256 allocatorMintingRate;\n    uint256 selfMintingRate;\n    uint256 lastChangeNotifiedBlock;\n}\n\n/**\n * @notice Distribution state information\n * @param lastDistributionBlock Last block where allocator-minting issuance was distributed\n * @param lastSelfMintingBlock Last block where self-minting issuance was applied\n * @param selfMintingOffset Self-minting that offsets allocator-minting budget (starts during pause, clears on distribution)\n */\nstruct DistributionState {\n    uint256 lastDistributionBlock;\n    uint256 lastSelfMintingBlock;\n    uint256 selfMintingOffset;\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/IIssuanceTarget.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title IIssuanceTarget\n * @author Edge & Node\n * @notice Interface for contracts that receive issuance from an issuance allocator\n */\ninterface IIssuanceTarget {\n    /**\n     * @notice New issuance allocator set\n     * @param oldIssuanceAllocator Old issuance allocator address\n     * @param newIssuanceAllocator New issuance allocator address\n     */\n    event IssuanceAllocatorSet(address indexed oldIssuanceAllocator, address indexed newIssuanceAllocator);\n\n    /**\n     * @notice Called by the issuance allocator before the target's issuance allocation changes\n     * @dev The target should ensure that all issuance related calculations are up-to-date\n     * with the current block so that an allocation change can be applied correctly.\n     * Note that the allocation could change multiple times in the same block after\n     * this function has been called, only the final allocation is relevant.\n     */\n    function beforeIssuanceAllocationChange() external;\n\n    /**\n     * @notice Sets the issuance allocator for this target\n     * @dev This function facilitates upgrades by providing a standard way for targets\n     * to change their allocator. Implementations can define their own access control.\n     * @param newIssuanceAllocator Address of the issuance allocator\n     */\n    function setIssuanceAllocator(address newIssuanceAllocator) external;\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/allocate/ISendTokens.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title ISendTokens\n * @author Edge & Node\n * @notice Interface for contracts that can send tokens to arbitrary addresses\n * @dev This interface provides a simple token transfer capability for contracts\n * that need to distribute or send tokens programmatically.\n */\ninterface ISendTokens {\n    /**\n     * @notice Send tokens to a specified address\n     * @param to The address to send tokens to\n     * @param amount The amount of tokens to send\n     */\n    function sendTokens(address to, uint256 amount) external;\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/common/IPausableControl.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title IPausableControl\n * @author Edge & Node\n * @notice Interface for contracts that support pause/unpause functionality\n * @dev This interface extends standard pausable functionality with explicit\n * pause and unpause functions. Contracts implementing this interface allow\n * authorized accounts to pause and unpause contract operations.\n * Events (Paused, Unpaused) are inherited from OpenZeppelin's PausableUpgradeable.\n */\ninterface IPausableControl {\n    /**\n     * @notice Pause the contract\n     * @dev Pauses contract operations. Only functions using whenNotPaused\n     * modifier will be affected.\n     */\n    function pause() external;\n\n    /**\n     * @notice Unpause the contract\n     * @dev Resumes contract operations. Only functions using whenPaused\n     * modifier will be affected.\n     */\n    function unpause() external;\n\n    /**\n     * @notice Check if the contract is currently paused\n     * @return True if the contract is paused, false otherwise\n     */\n    function paused() external view returns (bool);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/eligibility/IRewardsEligibility.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title IRewardsEligibility\n * @author Edge & Node\n * @notice Minimal interface for checking indexer rewards eligibility\n * @dev This is the interface that consumers (e.g., RewardsManager) need to check\n * if an indexer is eligible to receive rewards\n */\ninterface IRewardsEligibility {\n    /**\n     * @notice Check if an indexer is eligible to receive rewards\n     * @param indexer Address of the indexer\n     * @return True if the indexer is eligible to receive rewards, false otherwise\n     */\n    function isEligible(address indexer) external view returns (bool);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/eligibility/IRewardsEligibilityAdministration.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\nimport { IRewardsEligibilityEvents } from \"./IRewardsEligibilityEvents.sol\";\n\n/**\n * @title IRewardsEligibilityAdministration\n * @author Edge & Node\n * @notice Interface for administrative operations on rewards eligibility\n * @dev Functions in this interface are restricted to accounts with OPERATOR_ROLE\n */\ninterface IRewardsEligibilityAdministration is IRewardsEligibilityEvents {\n    /**\n     * @notice Set the eligibility period for indexers\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param eligibilityPeriod New eligibility period in seconds\n     * @return True if the state is as requested (eligibility period is set to the specified value)\n     */\n    function setEligibilityPeriod(uint256 eligibilityPeriod) external returns (bool);\n\n    /**\n     * @notice Set the oracle update timeout\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param oracleUpdateTimeout New timeout period in seconds\n     * @return True if the state is as requested (timeout is set to the specified value)\n     */\n    function setOracleUpdateTimeout(uint256 oracleUpdateTimeout) external returns (bool);\n\n    /**\n     * @notice Set eligibility validation state\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param enabled True to enable eligibility validation, false to disable\n     * @return True if successfully set (always the case for current code)\n     */\n    function setEligibilityValidation(bool enabled) external returns (bool);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/eligibility/IRewardsEligibilityEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title IRewardsEligibilityEvents\n * @author Edge & Node\n * @notice Shared events for rewards eligibility interfaces\n */\ninterface IRewardsEligibilityEvents {\n    /// @notice Emitted when an oracle submits eligibility data\n    /// @param oracle The address of the oracle that submitted the data\n    /// @param data The eligibility data submitted by the oracle\n    event IndexerEligibilityData(address indexed oracle, bytes data);\n\n    /// @notice Emitted when an indexer's eligibility is renewed by an oracle\n    /// @param indexer The address of the indexer whose eligibility was renewed\n    /// @param oracle The address of the oracle that renewed the indexer's eligibility\n    event IndexerEligibilityRenewed(address indexed indexer, address indexed oracle);\n\n    /// @notice Emitted when the eligibility period is updated\n    /// @param oldPeriod The previous eligibility period in seconds\n    /// @param newPeriod The new eligibility period in seconds\n    event EligibilityPeriodUpdated(uint256 indexed oldPeriod, uint256 indexed newPeriod);\n\n    /// @notice Emitted when eligibility validation is enabled or disabled\n    /// @param enabled True if eligibility validation is enabled, false if disabled\n    event EligibilityValidationUpdated(bool indexed enabled);\n\n    /// @notice Emitted when the oracle update timeout is updated\n    /// @param oldTimeout The previous timeout period in seconds\n    /// @param newTimeout The new timeout period in seconds\n    event OracleUpdateTimeoutUpdated(uint256 indexed oldTimeout, uint256 indexed newTimeout);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/eligibility/IRewardsEligibilityReporting.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\nimport { IRewardsEligibilityEvents } from \"./IRewardsEligibilityEvents.sol\";\n\n/**\n * @title IRewardsEligibilityReporting\n * @author Edge & Node\n * @notice Interface for oracle reporting of indexer eligibility\n * @dev Functions in this interface are restricted to accounts with ORACLE_ROLE\n */\ninterface IRewardsEligibilityReporting is IRewardsEligibilityEvents {\n    /**\n     * @notice Renew eligibility for provided indexers to receive rewards\n     * @param indexers Array of indexer addresses. Zero addresses are ignored.\n     * @param data Arbitrary calldata for future extensions\n     * @return Number of indexers whose eligibility renewal timestamp was updated\n     */\n    function renewIndexerEligibility(address[] calldata indexers, bytes calldata data) external returns (uint256);\n}\n"
      },
      "npm/@graphprotocol/interfaces@local/contracts/issuance/eligibility/IRewardsEligibilityStatus.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.6 || ^0.8.0;\n\n/**\n * @title IRewardsEligibilityStatus\n * @author Edge & Node\n * @notice Interface for querying rewards eligibility status and configuration\n * @dev All functions are view-only and can be called by anyone\n */\ninterface IRewardsEligibilityStatus {\n    /**\n     * @notice Get the last eligibility renewal timestamp for an indexer\n     * @param indexer Address of the indexer\n     * @return The last eligibility renewal timestamp, or 0 if the indexer's eligibility has never been renewed\n     */\n    function getEligibilityRenewalTime(address indexer) external view returns (uint256);\n\n    /**\n     * @notice Get the eligibility period\n     * @return The current eligibility period in seconds\n     */\n    function getEligibilityPeriod() external view returns (uint256);\n\n    /**\n     * @notice Get the oracle update timeout\n     * @return The current oracle update timeout in seconds\n     */\n    function getOracleUpdateTimeout() external view returns (uint256);\n\n    /**\n     * @notice Get the last oracle update time\n     * @return The timestamp of the last oracle update\n     */\n    function getLastOracleUpdateTime() external view returns (uint256);\n\n    /**\n     * @notice Get eligibility validation state\n     * @return True if eligibility validation is enabled, false otherwise\n     */\n    function getEligibilityValidation() external view returns (bool);\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/access/AccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {ERC165Upgradeable} from \"../utils/introspection/ERC165Upgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl\n    struct AccessControlStorage {\n        mapping(bytes32 role => RoleData) _roles;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.AccessControl\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;\n\n    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {\n        assembly {\n            $.slot := AccessControlStorageLocation\n        }\n    }\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    function __AccessControl_init() internal onlyInitializing {\n    }\n\n    function __AccessControl_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        $._roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (!hasRole(role, account)) {\n            $._roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (hasRole(role, account)) {\n            $._roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/access/extensions/AccessControlEnumerableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControlEnumerable} from \"@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol\";\nimport {AccessControlUpgradeable} from \"../AccessControlUpgradeable.sol\";\nimport {EnumerableSet} from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerable, AccessControlUpgradeable {\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControlEnumerable\n    struct AccessControlEnumerableStorage {\n        mapping(bytes32 role => EnumerableSet.AddressSet) _roleMembers;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.AccessControlEnumerable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant AccessControlEnumerableStorageLocation = 0xc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000;\n\n    function _getAccessControlEnumerableStorage() private pure returns (AccessControlEnumerableStorage storage $) {\n        assembly {\n            $.slot := AccessControlEnumerableStorageLocation\n        }\n    }\n\n    function __AccessControlEnumerable_init() internal onlyInitializing {\n    }\n\n    function __AccessControlEnumerable_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns one of the accounts that have `role`. `index` must be a\n     * value between 0 and {getRoleMemberCount}, non-inclusive.\n     *\n     * Role bearers are not sorted in any particular way, and their ordering may\n     * change at any point.\n     *\n     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n     * you perform all queries on the same block. See the following\n     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n     * for more information.\n     */\n    function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();\n        return $._roleMembers[role].at(index);\n    }\n\n    /**\n     * @dev Returns the number of accounts that have `role`. Can be used\n     * together with {getRoleMember} to enumerate all bearers of a role.\n     */\n    function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();\n        return $._roleMembers[role].length();\n    }\n\n    /**\n     * @dev Return all accounts that have `role`\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function getRoleMembers(bytes32 role) public view virtual returns (address[] memory) {\n        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();\n        return $._roleMembers[role].values();\n    }\n\n    /**\n     * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n     */\n    function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();\n        bool granted = super._grantRole(role, account);\n        if (granted) {\n            $._roleMembers[role].add(account);\n        }\n        return granted;\n    }\n\n    /**\n     * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();\n        bool revoked = super._revokeRole(role, account);\n        if (revoked) {\n            $._roleMembers[role].remove(account);\n        }\n        return revoked;\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.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 reinitialization) 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 Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\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        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/introspection/ERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165 {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    function __Pausable_init() internal onlyInitializing {\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/access/extensions/IAccessControlEnumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlEnumerable.sol)\n\npragma solidity >=0.8.4;\n\nimport {IAccessControl} from \"../IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n    /**\n     * @dev Returns one of the accounts that have `role`. `index` must be a\n     * value between 0 and {getRoleMemberCount}, non-inclusive.\n     *\n     * Role bearers are not sorted in any particular way, and their ordering may\n     * change at any point.\n     *\n     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n     * you perform all queries on the same block. See the following\n     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n     * for more information.\n     */\n    function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n    /**\n     * @dev Returns the number of accounts that have `role`. Can be used\n     * together with {getRoleMember} to enumerate all bearers of a role.\n     */\n    function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/access/IAccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted to signal this.\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/Arrays.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol)\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\n\npragma solidity ^0.8.20;\n\nimport {Comparators} from \"./Comparators.sol\";\nimport {SlotDerivation} from \"./SlotDerivation.sol\";\nimport {StorageSlot} from \"./StorageSlot.sol\";\nimport {Math} from \"./math/Math.sol\";\n\n/**\n * @dev Collection of functions related to array types.\n */\nlibrary Arrays {\n    using SlotDerivation for bytes32;\n    using StorageSlot for bytes32;\n\n    /**\n     * @dev Sort an array of uint256 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        uint256[] memory array,\n        function(uint256, uint256) pure returns (bool) comp\n    ) internal pure returns (uint256[] memory) {\n        _quickSort(_begin(array), _end(array), comp);\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\n     */\n    function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\n        sort(array, Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of address (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        address[] memory array,\n        function(address, address) pure returns (bool) comp\n    ) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of address in increasing order.\n     */\n    function sort(address[] memory array) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        bytes32[] memory array,\n        function(bytes32, bytes32) pure returns (bool) comp\n    ) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\n     */\n    function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\n     * at end (exclusive). Sorting follows the `comp` comparator.\n     *\n     * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\n     *\n     * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\n     * be used only if the limits are within a memory array.\n     */\n    function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\n        unchecked {\n            if (end - begin < 0x40) return;\n\n            // Use first element as pivot\n            uint256 pivot = _mload(begin);\n            // Position where the pivot should be at the end of the loop\n            uint256 pos = begin;\n\n            for (uint256 it = begin + 0x20; it < end; it += 0x20) {\n                if (comp(_mload(it), pivot)) {\n                    // If the value stored at the iterator's position comes before the pivot, we increment the\n                    // position of the pivot and move the value there.\n                    pos += 0x20;\n                    _swap(pos, it);\n                }\n            }\n\n            _swap(begin, pos); // Swap pivot into place\n            _quickSort(begin, pos, comp); // Sort the left side of the pivot\n            _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first element of `array`.\n     */\n    function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\n        assembly (\"memory-safe\") {\n            ptr := add(array, 0x20)\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\n     * that comes just after the last element of the array.\n     */\n    function _end(uint256[] memory array) private pure returns (uint256 ptr) {\n        unchecked {\n            return _begin(array) + array.length * 0x20;\n        }\n    }\n\n    /**\n     * @dev Load memory word (as a uint256) at location `ptr`.\n     */\n    function _mload(uint256 ptr) private pure returns (uint256 value) {\n        assembly {\n            value := mload(ptr)\n        }\n    }\n\n    /**\n     * @dev Swaps the elements memory location `ptr1` and `ptr2`.\n     */\n    function _swap(uint256 ptr1, uint256 ptr2) private pure {\n        assembly {\n            let value1 := mload(ptr1)\n            let value2 := mload(ptr2)\n            mstore(ptr1, value2)\n            mstore(ptr2, value1)\n        }\n    }\n\n    /// @dev Helper: low level cast address memory array to uint256 memory array\n    function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\n    function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast address comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(address, address) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(bytes32, bytes32) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /**\n     * @dev Searches a sorted `array` and returns the first index that contains\n     * a value greater or equal to `element`. If no such index exists (i.e. all\n     * values in the array are strictly less than `element`), the array length is\n     * returned. Time complexity O(log n).\n     *\n     * NOTE: The `array` is expected to be sorted in ascending order, and to\n     * contain no repeated elements.\n     *\n     * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\n     * support for repeated elements in the array. The {lowerBound} function should\n     * be used instead.\n     */\n    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\n        if (low > 0 && unsafeAccess(array, low - 1).value == element) {\n            return low - 1;\n        } else {\n            return low;\n        }\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value greater or equal than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\n     */\n    function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value strictly greater than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\n     */\n    function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {lowerBound}, but with an array in memory.\n     */\n    function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {upperBound}, but with an array in memory.\n     */\n    function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getAddressSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytes32Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getUint256Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytesSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getStringSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(address[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(uint256[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(string[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/Comparators.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to compare values.\n *\n * _Available since v5.1._\n */\nlibrary Comparators {\n    function lt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a < b;\n    }\n\n    function gt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a > b;\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\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 Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\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 ternary(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 ternary(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            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * 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            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 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 low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, 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 (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / 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 high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\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⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\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²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev 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        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\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     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\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 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\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 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\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"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.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/bool 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    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/Panic.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/ReentrancyGuardTransient.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol)\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n */\nabstract contract ReentrancyGuardTransient {\n    using TransientSlot for *;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\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        // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\n    }\n\n    function _nonReentrantAfter() private {\n        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\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        return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/SlotDerivation.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\n * the solidity language / compiler.\n *\n * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].\n *\n * Example usage:\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using StorageSlot for bytes32;\n *     using SlotDerivation for bytes32;\n *\n *     // Declare a namespace\n *     string private constant _NAMESPACE = \"<namespace>\"; // eg. OpenZeppelin.Slot\n *\n *     function setValueInNamespace(uint256 key, address newValue) internal {\n *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\n *     }\n *\n *     function getValueInNamespace(uint256 key) internal view returns (address) {\n *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {StorageSlot}.\n *\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\n * upgrade safety will ignore the slots accessed through this library.\n *\n * _Available since v5.1._\n */\nlibrary SlotDerivation {\n    /**\n     * @dev Derive an ERC-7201 slot from a string (namespace).\n     */\n    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\n            slot := and(keccak256(0x00, 0x20), not(0xff))\n        }\n    }\n\n    /**\n     * @dev Add an offset to a slot to get the n-th element of a structure or an array.\n     */\n    function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\n        unchecked {\n            return bytes32(uint256(slot) + pos);\n        }\n    }\n\n    /**\n     * @dev Derive the location of the first element in an array from the slot where the length is stored.\n     */\n    function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, slot)\n            result := keccak256(0x00, 0x20)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, and(key, shr(96, not(0))))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, iszero(iszero(key)))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.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 ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\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 *\n * TIP: Consider using this library along with {SlotDerivation}.\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 Int256Slot {\n        int256 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        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\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        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\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        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.20;\n\nimport {Arrays} from \"../Arrays.sol\";\nimport {Math} from \"../math/Math.sol\";\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n * - Set can be cleared (all elements removed) in O(n).\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * The following types are supported:\n *\n * - `bytes32` (`Bytes32Set`) since v3.3.0\n * - `address` (`AddressSet`) since v3.3.0\n * - `uint256` (`UintSet`) since v3.3.0\n * - `string` (`StringSet`) since v5.4.0\n * - `bytes` (`BytesSet`) since v5.4.0\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes32 value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that\n     * using it may render the function uncallable if the set grows to the point where clearing it consumes too much\n     * gas to fit in a block.\n     */\n    function _clear(Set storage set) private {\n        uint256 len = _length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {\n        unchecked {\n            end = Math.min(end, _length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes32[] memory result = new bytes32[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(Bytes32Set storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(AddressSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(UintSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    struct StringSet {\n        // Storage of set values\n        string[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(string value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(StringSet storage set, string memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(StringSet storage set, string memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                string memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(StringSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(StringSet storage set, string memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(StringSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(StringSet storage set, uint256 index) internal view returns (string memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set) internal view returns (string[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            string[] memory result = new string[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    struct BytesSet {\n        // Storage of set values\n        bytes[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(BytesSet storage set, bytes memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(BytesSet storage set, bytes memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(BytesSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(BytesSet storage set, bytes memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(BytesSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set) internal view returns (bytes[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes[] memory result = new bytes[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n}\n"
      },
      "npm/@openzeppelin/contracts@5.4.0/utils/TransientSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n *  * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n *     using TransientSlot for *;\n *\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n *     modifier locked() {\n *         require(!_LOCK_SLOT.asBoolean().tload());\n *\n *         _LOCK_SLOT.asBoolean().tstore(true);\n *         _;\n *         _LOCK_SLOT.asBoolean().tstore(false);\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n    /**\n     * @dev UDVT that represents a slot holding an address.\n     */\n    type AddressSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a AddressSlot.\n     */\n    function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n        return AddressSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a bool.\n     */\n    type BooleanSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a BooleanSlot.\n     */\n    function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n        return BooleanSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a bytes32.\n     */\n    type Bytes32Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Bytes32Slot.\n     */\n    function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n        return Bytes32Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a uint256.\n     */\n    type Uint256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Uint256Slot.\n     */\n    function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n        return Uint256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a int256.\n     */\n    type Int256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Int256Slot.\n     */\n    function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n        return Int256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(AddressSlot slot) internal view returns (address value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(AddressSlot slot, address value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(BooleanSlot slot) internal view returns (bool value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(BooleanSlot slot, bool value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Bytes32Slot slot, bytes32 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Uint256Slot slot) internal view returns (uint256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Uint256Slot slot, uint256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Int256Slot slot) internal view returns (int256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Int256Slot slot, int256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n}\n"
      },
      "project/contracts/allocate/DirectAllocation.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity 0.8.33;\n\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { ISendTokens } from \"@graphprotocol/interfaces/contracts/issuance/allocate/ISendTokens.sol\";\nimport { BaseUpgradeable } from \"../common/BaseUpgradeable.sol\";\n\n// solhint-disable-next-line no-unused-import\nimport { ERC165Upgradeable } from \"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\"; // Used by @inheritdoc\n\n/**\n * @title DirectAllocation\n * @author Edge & Node\n * @notice A simple contract that receives tokens from the IssuanceAllocator and allows\n * an authorized operator to withdraw them.\n *\n * @dev This contract is designed to be an allocator-minting target in the IssuanceAllocator.\n * The IssuanceAllocator will mint tokens directly to this contract, and the authorized\n * operator can send them to individual addresses as needed.\n *\n * This contract is pausable by the PAUSE_ROLE. When paused, tokens cannot be sent.\n * @custom:security-contact Please email security+contracts@thegraph.com if you find any bugs. We might have an active bug bounty program.\n */\ncontract DirectAllocation is BaseUpgradeable, IIssuanceTarget, ISendTokens {\n    // -- Custom Errors --\n\n    /// @notice Thrown when token transfer fails\n    /// @param to The address that the transfer was attempted to\n    /// @param amount The amount of tokens that failed to transfer\n    error SendTokensFailed(address to, uint256 amount);\n\n    // -- Events --\n\n    /// @notice Emitted when tokens are sent\n    /// @param to The address that received the tokens\n    /// @param amount The amount of tokens sent\n    event TokensSent(address indexed to, uint256 indexed amount);\n    // Do not need to index amount, ignoring gas-indexed-events warning.\n\n    /// @notice Emitted before the issuance allocation changes\n    event BeforeIssuanceAllocationChange();\n\n    // -- Constructor --\n\n    /**\n     * @notice Constructor for the DirectAllocation contract\n     * @dev This contract is upgradeable, but we use the constructor to pass the Graph Token address\n     * to the base contract.\n     * @param graphToken Address of the Graph Token contract\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(address graphToken) BaseUpgradeable(graphToken) {}\n\n    // -- Initialization --\n\n    /**\n     * @notice Initialize the DirectAllocation contract\n     * @param governor Address that will have the GOVERNOR_ROLE\n     */\n    function initialize(address governor) external virtual initializer {\n        __BaseUpgradeable_init(governor);\n    }\n\n    // -- ERC165 --\n\n    /**\n     * @inheritdoc ERC165Upgradeable\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IIssuanceTarget).interfaceId ||\n            interfaceId == type(ISendTokens).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    // -- External Functions --\n\n    /**\n     * @inheritdoc ISendTokens\n     */\n    function sendTokens(address to, uint256 amount) external override onlyRole(OPERATOR_ROLE) whenNotPaused {\n        require(GRAPH_TOKEN.transfer(to, amount), SendTokensFailed(to, amount));\n        emit TokensSent(to, amount);\n    }\n\n    /**\n     * @dev For DirectAllocation, this is a no-op since we don't need to perform any calculations\n     * before an allocation change. We simply receive tokens from the IssuanceAllocator.\n     * @inheritdoc IIssuanceTarget\n     */\n    function beforeIssuanceAllocationChange() external virtual override {\n        emit BeforeIssuanceAllocationChange();\n    }\n\n    /**\n     * @dev No-op for DirectAllocation; issuanceAllocator is not stored.\n     * @inheritdoc IIssuanceTarget\n     */\n    function setIssuanceAllocator(address issuanceAllocator) external virtual override onlyRole(GOVERNOR_ROLE) {}\n}\n"
      },
      "project/contracts/allocate/IssuanceAllocator.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity 0.8.33;\n\nimport {\n    TargetIssuancePerBlock,\n    Allocation,\n    AllocationTarget,\n    DistributionState,\n    SelfMintingEventMode\n} from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocatorTypes.sol\";\nimport { IIssuanceAllocationDistribution } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationDistribution.sol\";\nimport { IIssuanceAllocationAdministration } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationAdministration.sol\";\nimport { IIssuanceAllocationStatus } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationStatus.sol\";\nimport { IIssuanceAllocationData } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationData.sol\";\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { BaseUpgradeable } from \"../common/BaseUpgradeable.sol\";\nimport { ReentrancyGuardTransient } from \"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n// solhint-disable-next-line no-unused-import\nimport { ERC165Upgradeable } from \"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\"; // Used by @inheritdoc\n\n/**\n * @title IssuanceAllocator\n * @author Edge & Node\n * @notice This contract is responsible for allocating token issuance to different components\n * of the protocol. It calculates issuance for all targets based on their configured rates\n * (tokens per block) and handles minting for allocator-minting targets.\n *\n * @dev The contract maintains a 100% allocation invariant through a default target mechanism:\n * - A default target exists at targetAddresses[0] (initialized to address(0))\n * - The default target automatically receives any unallocated portion of issuance\n * - Total allocation across all targets always equals issuancePerBlock (tracked as absolute rates)\n * - The default target address can be changed via setDefaultTarget()\n * - When the default address is address(0), this 'unallocated' portion is not minted\n * - Regular targets cannot be set as the default target address\n *\n * @dev The contract supports two types of allocation for each target:\n * 1. Allocator-minting allocation: The IssuanceAllocator calculates and mints tokens directly to targets\n *    for this portion of their allocation.\n *\n * 2. Self-minting allocation: The IssuanceAllocator calculates issuance but does not mint tokens directly.\n *    Instead, targets are expected to call `getTargetIssuancePerBlock` to determine their self-minting\n *    issuance amount and mint tokens themselves. This feature is primarily intended for backwards\n *    compatibility with existing contracts like the RewardsManager.\n *\n * Each target can have both allocator-minting and self-minting allocations. New targets are expected\n * to use allocator-minting allocation to provide more robust control over token issuance through\n * the IssuanceAllocator. The self-minting allocation is intended only for backwards compatibility\n * with existing contracts.\n *\n * @dev Pause Behavior:\n * - Allocator-minting: Completely suspended during pause. No tokens minted, lastDistributionBlock frozen.\n *   When unpaused, distributes retroactively using current rates for entire undistributed period. (Distribution will be triggered by calling distributeIssuance() when not paused.)\n * - Self-minting: Continues tracking via events and accumulation during pause. Accumulated self-minting\n *   reduces allocator-minting budget when distribution resumes, ensuring total issuance conservation.\n * - Ongoing accumulation: Once accumulation starts (during pause), continues through any unpaused\n *   periods until distribution clears it, preventing loss of self-minting allowances across pause cycles.\n * - Tracking divergence: lastSelfMintingBlock advances during pause (for allowance tracking) while\n *   lastDistributionBlock stays frozen (no allocator-minting). This is intentional and correct.\n *\n * @dev Issuance Accounting Invariants:\n * The contract maintains strict accounting to ensure total token issuance never exceeds the configured\n * issuancePerBlock rate over any time period. This section provides the mathematical foundation for\n * understanding the relationship between self-minting and allocator-minting.\n *\n * Key Invariants:\n * 1. Allocation Completeness: For all blocks b, totalAllocatorRate_b + totalSelfMintingRate_b = issuancePerBlock_b\n *    This ensures 100% of issuance is always allocated across all targets.\n *\n * 2. Self-Minting Accumulation: For any undistributed block range [fromBlock, toBlock]:\n *    selfMintingOffset = Σ(totalSelfMintingRate_b) for all b in range\n *    where totalSelfMintingRate_b is the end-state rate for block b.\n *\n * 3. Rate Constraint: For all blocks b, totalSelfMintingRate_b ≤ issuancePerBlock_b\n *    This follows from invariant (1) since 0 ≤ totalAllocatorRate_b.\n *\n * 4. Issuance Upper Bound: For any distribution period with blocks = toBlock - fromBlock + 1:\n *    Let issuancePerBlock_final = current issuancePerBlock at distribution time\n *\n *    From invariants (2) and (3):\n *      selfMintingOffset ≤ Σ(issuancePerBlock_b)\n *\n *    Allocator-minting budget for period:\n *      available = max(0, issuancePerBlock_final * blocks - selfMintingOffset)\n *\n *    Total minted (self + allocator) for period:\n *      ≤ max(selfMintingOffset, issuancePerBlock_final * blocks)\n *      ≤ Σ(issuancePerBlock_b)\n *\n *    Therefore, total issuance never exceeds the sum of configured rates during the period.\n *\n * 5. Offset Reconciliation: During pending distribution, selfMintingOffset is adjusted to account for\n *    the period's issuance budget. When distribution catches up to current block, the offset is cleared.\n *    Any remaining offset when cleared represents self-minting that occurred beyond what the final\n *    issuancePerBlock rate would allow for the period. This is acceptable because:\n *    a) Self-minting targets were operating under rates that were valid at the time\n *    b) The total minted still respects the Σ(issuancePerBlock_b) bound (invariant 4)\n *    c) Clearing the offset prevents it from affecting future distributions\n *    d) The SelfMintingOffsetReconciled event provides visibility into all offset adjustments\n *\n * This design ensures that even when issuancePerBlock or allocation rates change over time, and even\n * when self-minting targets mint independently, the total tokens minted never exceeds the sum of\n * configured issuance rates during the period.\n *\n * @dev There are a number of scenarios where the IssuanceAllocator could run into issues, including:\n * 1. The targetAddresses array could grow large enough that it exceeds the gas limit when calling distributeIssuance.\n * 2. When notifying targets of allocation changes the calls to `beforeIssuanceAllocationChange` could exceed the gas limit.\n * 3. Target contracts could revert when notifying them of changes via `beforeIssuanceAllocationChange`.\n * While in practice the IssuanceAllocator is expected to have a relatively small number of trusted targets, and the\n * gas limit is expected to be high enough to handle the above scenarios, the following would allow recovery:\n * 1. The contract can be paused, which can help make the recovery process easier to manage.\n * 2. The GOVERNOR_ROLE can directly trigger change notification to individual targets. As there is per target\n *    tracking of the lastChangeNotifiedBlock, this can reduce the gas cost of other operations and allow\n *    for graceful recovery.\n * 3. If a target reverts when notifying it of changes or notifying it is too expensive, the GOVERNOR_ROLE can use `forceTargetNoChangeNotificationBlock()`\n *    to skip notifying that particular target of changes.\n *\n * In combination these should allow recovery from gas limit issues or malfunctioning targets, with fine-grained control over\n * which targets are notified of changes and when.\n *\n * @dev Reentrancy Protection:\n * The contract code is designed to be reentrant-safe and should be carefully reviewed and maintained\n * to preserve this property. However, reentrancy guards (using transient storage per EIP-1153) are\n * applied to governance functions that modify configuration or state as an additional layer of defense.\n * This provides protection against potential issues if the multi-sig governor role were to have known\n * signatures that could be exploited by malicious actors to trigger reentrant calls.\n *\n * The `distributeIssuance()` function intentionally does NOT have a reentrancy guard to allow\n * legitimate use cases where targets call it during notifications (e.g., to claim pending issuance\n * before allocation changes). This is safe because distributeIssuance() has built-in block-tracking\n * protection (preventing double-distribution in the same block), makes no external calls that could\n * expose inconsistent state, and does not modify allocations.\n * @custom:security-contact Please email security+contracts@thegraph.com if you find any bugs. We might have an active bug bounty program.\n */\ncontract IssuanceAllocator is\n    BaseUpgradeable,\n    ReentrancyGuardTransient,\n    IIssuanceAllocationDistribution,\n    IIssuanceAllocationAdministration,\n    IIssuanceAllocationStatus,\n    IIssuanceAllocationData\n{\n    // -- Namespaced Storage --\n\n    /// @notice ERC-7201 storage location for IssuanceAllocator\n    bytes32 private constant ISSUANCE_ALLOCATOR_STORAGE_LOCATION =\n        // solhint-disable-next-line gas-small-strings\n        keccak256(abi.encode(uint256(keccak256(\"graphprotocol.storage.IssuanceAllocator\")) - 1)) &\n            ~bytes32(uint256(0xff));\n\n    /// @notice Main storage structure for IssuanceAllocator using ERC-7201 namespaced storage\n    /// @param issuancePerBlock Total issuance per block across all targets\n    /// @param lastDistributionBlock Last block when allocator-minting issuance was distributed\n    /// @param lastSelfMintingBlock Last block when self-minting was advanced\n    /// @param selfMintingOffset Self-minting that offsets allocator-minting budget (accumulates during pause, clears on distribution)\n    /// @param allocationTargets Mapping of target addresses to their allocation data\n    /// @param targetAddresses Array of all target addresses (including default target at index 0)\n    /// @param totalSelfMintingRate Total self-minting rate (tokens per block) across all targets\n    /// @param selfMintingEventMode Controls self-minting event emission behavior (PerTarget, Aggregate, or None)\n    /// @dev Design invariant: totalAllocatorRate + totalSelfMintingRate == issuancePerBlock (always 100% allocated)\n    /// @dev Design invariant: targetAddresses[0] is always the default target address\n    /// @dev Design invariant: 1 <= targetAddresses.length (default target always exists)\n    /// @dev Design invariant: default target (targetAddresses[0]) is automatically adjusted to maintain 100% total\n    /// @custom:storage-location erc7201:graphprotocol.storage.IssuanceAllocator\n    struct IssuanceAllocatorData {\n        uint256 issuancePerBlock;\n        uint256 lastDistributionBlock;\n        uint256 lastSelfMintingBlock;\n        uint256 selfMintingOffset;\n        mapping(address => AllocationTarget) allocationTargets;\n        address[] targetAddresses;\n        uint256 totalSelfMintingRate;\n        SelfMintingEventMode selfMintingEventMode;\n    }\n\n    /**\n     * @notice Returns the storage struct for IssuanceAllocator\n     * @return $ contract storage\n     */\n    function _getIssuanceAllocatorStorage() private pure returns (IssuanceAllocatorData storage $) {\n        // solhint-disable-previous-line use-natspec\n        // Solhint does not support $ return variable in natspec\n\n        bytes32 slot = ISSUANCE_ALLOCATOR_STORAGE_LOCATION;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := slot\n        }\n    }\n\n    // -- Custom Errors --\n\n    /// @notice Thrown when attempting to add a target with zero address\n    error TargetAddressCannotBeZero();\n\n    /// @notice Thrown when the total allocation would exceed available budget\n    /// @param requested The total requested allocation (allocator + self minting)\n    /// @param available The available budget for this target\n    error InsufficientAllocationAvailable(uint256 requested, uint256 available);\n\n    /// @notice Thrown when attempting to decrease issuance rate without sufficient unallocated budget\n    /// @param oldRate The current issuance rate\n    /// @param newRate The proposed new issuance rate\n    /// @param unallocated The unallocated budget available to absorb the decrease\n    error InsufficientUnallocatedForRateDecrease(uint256 oldRate, uint256 newRate, uint256 unallocated);\n\n    /// @notice Thrown when a target does not support the IIssuanceTarget interface\n    /// @param target The target address that doesn't support the interface\n    error TargetDoesNotSupportIIssuanceTarget(address target);\n\n    /// @notice Thrown when toBlockNumber is out of valid range for accumulation\n    /// @param toBlock The invalid block number provided\n    /// @param minBlock The minimum valid block number (lastDistributionBlock)\n    /// @param maxBlock The maximum valid block number (current block)\n    error ToBlockOutOfRange(uint256 toBlock, uint256 minBlock, uint256 maxBlock);\n\n    /// @notice Thrown when attempting to set allocation for the default target\n    /// @param defaultTarget The address of the default target\n    error CannotSetAllocationForDefaultTarget(address defaultTarget);\n\n    /// @notice Thrown when attempting to set default target address to a normally allocated target\n    /// @param target The target address that already has an allocation\n    error CannotSetDefaultToAllocatedTarget(address target);\n\n    // -- Events --\n\n    /// @notice Emitted when issuance is distributed to a target\n    /// @param target The address of the target that received issuance\n    /// @param amount The amount of tokens distributed\n    /// @param fromBlock First block included in this distribution (inclusive)\n    /// @param toBlock Last block included in this distribution (inclusive). Range is [fromBlock, toBlock]\n    event IssuanceDistributed(\n        address indexed target,\n        uint256 amount,\n        uint256 indexed fromBlock,\n        uint256 indexed toBlock\n    ); // solhint-disable-line gas-indexed-events\n\n    /// @notice Emitted when a target's allocation is updated\n    /// @param target The address of the target whose allocation was updated\n    /// @param newAllocatorMintingRate The new allocator-minting rate (tokens per block) for the target\n    /// @param newSelfMintingRate The new self-minting rate (tokens per block) for the target\n    event TargetAllocationUpdated(address indexed target, uint256 newAllocatorMintingRate, uint256 newSelfMintingRate); // solhint-disable-line gas-indexed-events\n    // Do not need to index rate values\n\n    /// @notice Emitted when the issuance per block is updated\n    /// @param oldIssuancePerBlock The previous issuance per block amount\n    /// @param newIssuancePerBlock The new issuance per block amount\n    event IssuancePerBlockUpdated(uint256 oldIssuancePerBlock, uint256 newIssuancePerBlock); // solhint-disable-line gas-indexed-events\n    // Do not need to index issuance per block values\n\n    /// @notice Emitted when the default target is updated\n    /// @param oldAddress The previous default target address\n    /// @param newAddress The new default target address\n    event DefaultTargetUpdated(address indexed oldAddress, address indexed newAddress);\n\n    /// @notice Emitted when self-minting allowance is calculated for a target\n    /// @param target The address of the target with self-minting allocation\n    /// @param amount The amount of tokens available for self-minting\n    /// @param fromBlock First block included in this allowance period (inclusive)\n    /// @param toBlock Last block included in this allowance period (inclusive). Range is [fromBlock, toBlock]\n    event IssuanceSelfMintAllowance(\n        address indexed target,\n        uint256 amount,\n        uint256 indexed fromBlock,\n        uint256 indexed toBlock\n    ); // solhint-disable-line gas-indexed-events\n\n    /* solhint-disable gas-indexed-events */\n    /// @notice Emitted when self-minting offset is reconciled during pending distribution\n    /// @param offsetBefore The self-minting offset before reconciliation\n    /// @param offsetAfter The self-minting offset after reconciliation (0 when caught up to current block)\n    /// @param totalForPeriod The total issuance budget for the distributed period\n    /// @param fromBlock First block in the distribution period (inclusive)\n    /// @param toBlock Last block in the distribution period (inclusive)\n    /// @dev This event provides visibility into the accounting reconciliation between self-minting\n    /// and allocator-minting budgets during pending distribution. When offsetAfter is 0, the contract\n    /// has fully caught up with distribution. When offsetAfter > 0, there remains accumulated offset\n    /// that will be applied to future distributions.\n    event SelfMintingOffsetReconciled(\n        uint256 offsetBefore,\n        uint256 offsetAfter,\n        uint256 totalForPeriod,\n        uint256 indexed fromBlock,\n        uint256 indexed toBlock\n    );\n    /* solhint-enable gas-indexed-events */\n\n    /* solhint-disable gas-indexed-events */\n    /// @notice Emitted when self-minting offset accumulates during pause or catch-up\n    /// @param offsetBefore The self-minting offset before accumulation\n    /// @param offsetAfter The self-minting offset after accumulation\n    /// @param fromBlock First block in the accumulation period (inclusive)\n    /// @param toBlock Last block in the accumulation period (inclusive)\n    /// @dev This event provides visibility into offset growth during pause periods or while catching up\n    /// after unpause. Together with SelfMintingOffsetReconciled, provides complete accounting of all\n    /// offset changes.\n    event SelfMintingOffsetAccumulated(\n        uint256 offsetBefore,\n        uint256 offsetAfter,\n        uint256 indexed fromBlock,\n        uint256 indexed toBlock\n    );\n    /* solhint-enable gas-indexed-events */\n\n    /// @notice Emitted when self-minting allowance is calculated in aggregate mode\n    /// @param totalAmount The total amount of tokens available for self-minting across all targets\n    /// @param fromBlock First block included in this allowance period (inclusive)\n    /// @param toBlock Last block included in this allowance period (inclusive)\n    /// @dev This event is emitted when selfMintingEventMode is Aggregate, providing a single event\n    /// instead of per-target events to reduce gas costs\n    event IssuanceSelfMintAllowanceAggregate(uint256 totalAmount, uint256 indexed fromBlock, uint256 indexed toBlock); // solhint-disable-line gas-indexed-events\n\n    /// @notice Emitted when self-minting event mode is changed\n    /// @param oldMode The previous event emission mode\n    /// @param newMode The new event emission mode\n    event SelfMintingEventModeUpdated(SelfMintingEventMode oldMode, SelfMintingEventMode newMode);\n\n    // -- Constructor --\n\n    /**\n     * @notice Constructor for the IssuanceAllocator contract\n     * @dev This contract is upgradeable, but we use the constructor to pass the Graph Token address\n     * to the base contract.\n     * @param _graphToken Address of the Graph Token contract\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(address _graphToken) BaseUpgradeable(_graphToken) {}\n\n    // -- Initialization --\n\n    /**\n     * @notice Initialize the IssuanceAllocator contract\n     * @param _governor Address that will have the GOVERNOR_ROLE\n     * @dev Initializes with a default target at index 0 set to address(0)\n     * @dev Default target will receive all unallocated issuance (initially 0 until rate is set)\n     * @dev lastDistributionBlock is set to block.number as a safety guard against pausing before\n     * configuration. lastSelfMintingBlock defaults to 0. issuancePerBlock is 0. Once\n     * setIssuancePerBlock() is called, it triggers _distributeIssuance() which updates\n     * lastDistributionBlock to current block, establishing the starting point for issuance tracking.\n     * @dev selfMintingEventMode is initialized to PerTarget\n     */\n    function initialize(address _governor) external virtual initializer {\n        __BaseUpgradeable_init(_governor);\n\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        // Initialize default target at index 0 with address(0)\n        // Rates are 0 initially; default gets remainder when issuancePerBlock is set\n        $.targetAddresses.push(address(0));\n\n        $.selfMintingEventMode = SelfMintingEventMode.PerTarget;\n\n        // To guard against extreme edge case of pausing before setting issuancePerBlock, we initialize\n        // lastDistributionBlock to block.number. This should be updated to the correct starting block\n        // during configuration by governance.\n        $.lastDistributionBlock = block.number;\n    }\n\n    // -- Core Functionality --\n\n    /**\n     * @inheritdoc ERC165Upgradeable\n     * @dev Supports the four IssuanceAllocator sub-interfaces\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IIssuanceAllocationDistribution).interfaceId ||\n            interfaceId == type(IIssuanceAllocationAdministration).interfaceId ||\n            interfaceId == type(IIssuanceAllocationStatus).interfaceId ||\n            interfaceId == type(IIssuanceAllocationData).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationDistribution\n     * @dev Implementation details:\n     * - For allocator-minting targets, tokens are minted and transferred directly to targets based on their allocation rate\n     * - For self-minting targets (like the legacy RewardsManager), it does not mint tokens directly. Instead, these contracts are expected to handle minting themselves\n     * - The self-minting allocation is intended only for backwards compatibility with existing contracts and should not be used for new targets. New targets should use allocator-minting allocation to ensure robust control of token issuance by the IssuanceAllocator\n     * @dev Pause behavior:\n     * - When paused: Self-minting allowances tracked via events/accumulation, but no allocator-minting tokens distributed.\n     *   Returns lastDistributionBlock (frozen at pause point). lastSelfMintingBlock advances to current block.\n     * - When unpaused: Normal distribution if no accumulated self-minting, otherwise retroactive distribution\n     *   using current rates for entire undistributed period, with accumulated self-minting reducing allocator budget.\n     * - Unless paused, always advances lastDistributionBlock to block.number, even if no issuance to distribute.\n     * @dev Reentrancy: This function intentionally does NOT have a reentrancy guard to allow targets to\n     * legitimately call it during notifications (e.g., to claim pending issuance before their allocation changes).\n     * This is safe because the function has built-in block-tracking protection that prevents double-distribution\n     * within the same block, makes no external calls that could expose inconsistent state, and does not modify allocations.\n     */\n    function distributeIssuance() external override returns (uint256) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        // Optimize common case: if already distributed this block, return immediately (~60% gas savings).\n        // Multiple targets may call this in the same block; first call distributes, rest are no-ops.\n        return $.lastDistributionBlock == block.number ? block.number : _distributeIssuance();\n    }\n\n    /**\n     * @notice Advances self-minting block and emits allowance events\n     * @dev When paused, accumulates self-minting amounts. This accumulation reduces the allocator-minting\n     * budget when distribution resumes, ensuring total issuance stays within bounds.\n     * When not paused, emits self-minting allowance events based on selfMintingEventMode.\n     * Called by _distributeIssuance() which anyone can call.\n     * Optimized for no-op cases: very cheap when already at current block.\n     */\n    function _advanceSelfMintingBlock() private {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        uint256 previousBlock = $.lastSelfMintingBlock;\n        if (previousBlock == block.number) return;\n\n        uint256 blocks = block.number - previousBlock;\n        uint256 fromBlock = previousBlock + 1;\n\n        // Accumulate if currently paused OR if there's existing accumulated balance.\n        // Once accumulation starts (during pause), continue through any unpaused periods\n        // until distribution clears the accumulation. This is conservative and allows\n        // better recovery when distribution is delayed through pause/unpause cycles.\n        uint256 offsetBefore = $.selfMintingOffset;\n        if (paused() || 0 < offsetBefore) {\n            $.selfMintingOffset += $.totalSelfMintingRate * blocks;\n\n            // Emit accumulation event whenever offset changes\n            if (offsetBefore != $.selfMintingOffset) {\n                emit SelfMintingOffsetAccumulated(offsetBefore, $.selfMintingOffset, fromBlock, block.number);\n            }\n        }\n        $.lastSelfMintingBlock = block.number;\n\n        // Emit self-minting allowance events based on mode\n        if (0 < $.totalSelfMintingRate) {\n            if ($.selfMintingEventMode == SelfMintingEventMode.PerTarget) {\n                // Emit per-target events (highest gas cost)\n                for (uint256 i = 0; i < $.targetAddresses.length; ++i) {\n                    address target = $.targetAddresses[i];\n                    AllocationTarget storage targetData = $.allocationTargets[target];\n\n                    if (0 < targetData.selfMintingRate) {\n                        uint256 amount = targetData.selfMintingRate * blocks;\n                        emit IssuanceSelfMintAllowance(target, amount, fromBlock, block.number);\n                    }\n                }\n            } else if ($.selfMintingEventMode == SelfMintingEventMode.Aggregate) {\n                // Emit single aggregated event (lower gas cost)\n                uint256 totalAmount = $.totalSelfMintingRate * blocks;\n                emit IssuanceSelfMintAllowanceAggregate(totalAmount, fromBlock, block.number);\n            }\n            // else None: skip event emission entirely (lowest gas cost)\n        }\n    }\n\n    /**\n     * @notice Internal implementation for `distributeIssuance`\n     * @dev Handles the actual distribution logic.\n     * @dev Always calls _advanceSelfMintingBlock() first (advances lastSelfMintingBlock, tracks self-minting).\n     * @dev If paused: Returns lastDistributionBlock without distributing allocator-minting (frozen state).\n     * @dev If unpaused: Chooses distribution path based on accumulated self-minting:\n     *      - With accumulation: retroactive distribution path (current rates, reduced allocator budget)\n     *      - Without accumulation: normal distribution path (simple per-block minting)\n     * @return Block number distributed to\n     */\n    function _distributeIssuance() private returns (uint256) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        _advanceSelfMintingBlock();\n\n        if (paused()) return $.lastDistributionBlock;\n\n        return 0 < $.selfMintingOffset ? _distributePendingIssuance(block.number) : _performNormalDistribution();\n    }\n\n    /**\n     * @notice Performs normal (non-pending) issuance distribution\n     * @dev Distributes allocator-minting issuance to all targets based on their rates\n     * @dev Assumes contract is not paused and pending issuance has already been distributed\n     * @return Block number distributed to\n     */\n    function _performNormalDistribution() private returns (uint256) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        uint256 blocks = block.number - $.lastDistributionBlock;\n        if (blocks == 0) return $.lastDistributionBlock;\n\n        uint256 fromBlock = $.lastDistributionBlock + 1;\n\n        for (uint256 i = 0; i < $.targetAddresses.length; ++i) {\n            address target = $.targetAddresses[i];\n            if (target == address(0)) continue;\n\n            AllocationTarget storage targetData = $.allocationTargets[target];\n            if (0 < targetData.allocatorMintingRate) {\n                uint256 amount = targetData.allocatorMintingRate * blocks;\n                GRAPH_TOKEN.mint(target, amount);\n                emit IssuanceDistributed(target, amount, fromBlock, block.number);\n            }\n        }\n\n        $.lastDistributionBlock = block.number;\n        return block.number;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function distributePendingIssuance() external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (uint256) {\n        return _distributePendingIssuance(block.number);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function distributePendingIssuance(\n        uint256 toBlockNumber\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (uint256) {\n        return _distributePendingIssuance(toBlockNumber);\n    }\n\n    /**\n     * @notice Internal implementation for distributing pending accumulated allocator-minting issuance\n     * @param toBlockNumber Block number to distribute up to\n     * @dev Distributes allocator-minting issuance for undistributed period using current rates,\n     * retroactively applied from lastDistributionBlock to toBlockNumber (inclusive).\n     * Called when 0 < selfMintingOffset, which occurs after pause periods or delayed distribution.\n     * @dev Available budget = max(0, issuancePerBlock * blocks - selfMintingOffset).\n     * Distribution cases:\n     * (1) available < allocatedTotal: proportional distribution to non-default, default gets zero\n     * (2) allocatedTotal <= available: full rates to non-default, remainder to default\n     * Where allocatedTotal is sum of non-default allocator rates * blocks.\n     * @return Block number that issuance was distributed up to\n     */\n    function _distributePendingIssuance(uint256 toBlockNumber) private returns (uint256) {\n        _advanceSelfMintingBlock();\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        require(\n            $.lastDistributionBlock <= toBlockNumber && toBlockNumber <= block.number, // solhint-disable-line gas-strict-inequalities\n            ToBlockOutOfRange(toBlockNumber, $.lastDistributionBlock, block.number)\n        );\n\n        uint256 blocks = toBlockNumber - $.lastDistributionBlock;\n        if (blocks == 0) return toBlockNumber;\n\n        // Overflow is not possible with reasonable parameters. For example, with issuancePerBlock\n        // at 1e24 (1 million GRT with 18 decimals) and blocks at 1e9 (hundreds of years), the product is\n        // ~1e33, well below uint256 max (~1e77). Similar multiplications throughout this contract operate\n        // under the same range assumptions.\n        uint256 totalForPeriod = $.issuancePerBlock * blocks;\n        uint256 selfMintingOffset = $.selfMintingOffset;\n\n        uint256 available = selfMintingOffset < totalForPeriod ? totalForPeriod - selfMintingOffset : 0;\n\n        if (0 < available) {\n            // Calculate non-default allocated rate using the allocation invariant.\n            // Since totalAllocatorRate + totalSelfMintingRate == issuancePerBlock (100% invariant),\n            // and default target is part of totalAllocatorRate, we can derive:\n            // allocatedRate = issuancePerBlock - totalSelfMintingRate - defaultAllocatorRate\n            address defaultAddress = $.targetAddresses[0];\n            AllocationTarget storage defaultTarget = $.allocationTargets[defaultAddress];\n            uint256 allocatedRate = $.issuancePerBlock - $.totalSelfMintingRate - defaultTarget.allocatorMintingRate;\n\n            uint256 allocatedTotal = allocatedRate * blocks;\n\n            if (available < allocatedTotal) _distributePendingProportionally(available, allocatedRate, toBlockNumber);\n            else _distributePendingWithFullRate(blocks, available, allocatedTotal, toBlockNumber);\n        }\n\n        $.lastDistributionBlock = toBlockNumber;\n        _reconcileSelfMintingOffset(toBlockNumber, blocks, totalForPeriod, selfMintingOffset);\n        return toBlockNumber;\n    }\n\n    /**\n     * @notice Reconciles self-minting offset after distribution and emits event if changed\n     * @param toBlockNumber Block number distributed to\n     * @param blocks Number of blocks in the distribution period\n     * @param totalForPeriod Total issuance budget for the period\n     * @param selfMintingOffset Self-minting offset before reconciliation\n     * @dev Updates accumulated self-minting after distribution.\n     * Subtracts the period budget used (min of accumulated and totalForPeriod).\n     * When caught up to current block, clears all since nothing remains to distribute.\n     */\n    function _reconcileSelfMintingOffset(\n        uint256 toBlockNumber,\n        uint256 blocks,\n        uint256 totalForPeriod,\n        uint256 selfMintingOffset\n    ) private {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        uint256 newOffset = toBlockNumber == block.number\n            ? 0\n            : (totalForPeriod < selfMintingOffset ? selfMintingOffset - totalForPeriod : 0);\n\n        // Emit reconciliation event whenever offset changes during pending distribution\n        if (selfMintingOffset != newOffset) {\n            emit SelfMintingOffsetReconciled(\n                selfMintingOffset,\n                newOffset,\n                totalForPeriod,\n                toBlockNumber - blocks + 1,\n                toBlockNumber\n            );\n        }\n\n        $.selfMintingOffset = newOffset;\n    }\n\n    /**\n     * @notice Distribute pending issuance with full rates to non-default targets\n     * @param blocks Number of blocks in the distribution period\n     * @param available Total available allocator-minting budget for the period\n     * @param allocatedTotal Total amount allocated to non-default targets at full rate\n     * @param toBlockNumber Block number distributing to\n     * @dev Sufficient budget: non-default targets get full rates, default gets remainder\n     */\n    function _distributePendingWithFullRate(\n        uint256 blocks,\n        uint256 available,\n        uint256 allocatedTotal,\n        uint256 toBlockNumber\n    ) internal {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        uint256 fromBlock = $.lastDistributionBlock + 1;\n\n        // Give non-default targets their full rates\n        for (uint256 i = 1; i < $.targetAddresses.length; ++i) {\n            address target = $.targetAddresses[i];\n            AllocationTarget storage targetData = $.allocationTargets[target];\n\n            if (0 < targetData.allocatorMintingRate) {\n                uint256 amount = targetData.allocatorMintingRate * blocks;\n                GRAPH_TOKEN.mint(target, amount);\n                emit IssuanceDistributed(target, amount, fromBlock, toBlockNumber);\n            }\n        }\n\n        // Default target gets remainder (may be 0 if exactly matched)\n        uint256 remainingForDefault = available - allocatedTotal;\n        if (0 < remainingForDefault) {\n            address defaultAddress = $.targetAddresses[0];\n            if (defaultAddress != address(0)) {\n                GRAPH_TOKEN.mint(defaultAddress, remainingForDefault);\n                emit IssuanceDistributed(defaultAddress, remainingForDefault, fromBlock, toBlockNumber);\n            }\n        }\n    }\n\n    /**\n     * @notice Distribute pending issuance proportionally among non-default targets\n     * @param available Total available allocator-minting budget for the period\n     * @param allocatedRate Total rate allocated to non-default targets\n     * @param toBlockNumber Block number distributing to\n     * @dev Insufficient budget: non-default targets get proportional shares, default gets zero\n     * @dev Proportional distribution may result in rounding loss (dust), which is acceptable\n     */\n    function _distributePendingProportionally(\n        uint256 available,\n        uint256 allocatedRate,\n        uint256 toBlockNumber\n    ) internal {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        // Defensive: prevent division by zero and handle edge cases. Should not be reachable based on\n        // caller logic (only called when available < allocatedTotal and both available > 0, blocks > 0).\n        if (allocatedRate == 0 || available == 0) return;\n\n        uint256 fromBlock = $.lastDistributionBlock + 1;\n\n        // Non-default targets get proportional shares (reduced amounts)\n        // Default is excluded (receives zero)\n        for (uint256 i = 1; i < $.targetAddresses.length; ++i) {\n            address target = $.targetAddresses[i];\n            AllocationTarget storage targetData = $.allocationTargets[target];\n\n            if (0 < targetData.allocatorMintingRate) {\n                // Proportional distribution using integer division causes rounding loss.\n                // Since Solidity division always floors (truncates toward zero), this can ONLY lose tokens,\n                // never over-distribute. The lost tokens (dust) remain unallocated.\n                // This is acceptable because:\n                // 1. The amount is negligible (< number of targets)\n                // 2. It maintains safety (never over-mint)\n                // 3. Alternative of tracking and distributing dust adds complexity without significant benefit\n                uint256 amount = (available * targetData.allocatorMintingRate) / allocatedRate;\n                GRAPH_TOKEN.mint(target, amount);\n                emit IssuanceDistributed(target, amount, fromBlock, toBlockNumber);\n            }\n        }\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setIssuancePerBlock(\n        uint256 newIssuancePerBlock\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setIssuancePerBlock(newIssuancePerBlock, block.number);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     * @dev Implementation details:\n     * - Requires distribution to have reached at least minDistributedBlock\n     * - This allows configuration changes after calling distributePendingIssuance(blockNumber) while paused\n     * - Only the default target is notified (target rates don't change, only default target changes)\n     * - Target rates stay fixed; default target absorbs the change\n     * - Whenever the rate is changed, the updateL2MintAllowance function _must_ be called on the L1GraphTokenGateway in L1, to ensure the bridge can mint the right amount of tokens\n     * @dev Rate changes while paused: The new rate applies retroactively to the entire undistributed\n     * period when distribution resumes. Governance must exercise caution to ensure rates are applied\n     * to the correct block range. Use distributePendingIssuance(blockNumber) to control precisely\n     * which block the new rate applies from.\n     */\n    function setIssuancePerBlock(\n        uint256 newIssuancePerBlock,\n        uint256 minDistributedBlock\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setIssuancePerBlock(newIssuancePerBlock, minDistributedBlock);\n    }\n\n    /**\n     * @notice Internal implementation for setting issuance per block\n     * @param newIssuancePerBlock New issuance per block\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return True if the value is applied\n     */\n    function _setIssuancePerBlock(uint256 newIssuancePerBlock, uint256 minDistributedBlock) private returns (bool) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        uint256 oldIssuancePerBlock = $.issuancePerBlock;\n        if (newIssuancePerBlock == oldIssuancePerBlock) return true;\n\n        if (_distributeIssuance() < minDistributedBlock) return false;\n\n        _notifyTarget($.targetAddresses[0]);\n\n        AllocationTarget storage defaultTarget = $.allocationTargets[$.targetAddresses[0]];\n        uint256 unallocated = defaultTarget.allocatorMintingRate;\n\n        require(\n            oldIssuancePerBlock <= newIssuancePerBlock + unallocated, // solhint-disable-line gas-strict-inequalities\n            InsufficientUnallocatedForRateDecrease(oldIssuancePerBlock, newIssuancePerBlock, unallocated)\n        );\n\n        defaultTarget.allocatorMintingRate = unallocated + newIssuancePerBlock - oldIssuancePerBlock;\n        $.issuancePerBlock = newIssuancePerBlock;\n\n        emit IssuancePerBlockUpdated(oldIssuancePerBlock, newIssuancePerBlock);\n\n        return true;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setSelfMintingEventMode(SelfMintingEventMode newMode) external onlyRole(GOVERNOR_ROLE) returns (bool) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        SelfMintingEventMode oldMode = $.selfMintingEventMode;\n\n        if (newMode == oldMode) return true;\n\n        $.selfMintingEventMode = newMode;\n        emit SelfMintingEventModeUpdated(oldMode, newMode);\n\n        return true;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function getSelfMintingEventMode() external view override returns (SelfMintingEventMode) {\n        return _getIssuanceAllocatorStorage().selfMintingEventMode;\n    }\n\n    // -- Target Management --\n\n    /**\n     * @notice Internal function to notify a target about an upcoming allocation change\n     * @dev Uses per-target lastChangeNotifiedBlock to prevent reentrancy and duplicate notifications.\n     *\n     * Will revert if the target's beforeIssuanceAllocationChange call fails.\n     * Use forceTargetNoChangeNotificationBlock to skip notification for malfunctioning targets.\n     *\n     * @param target Address of the target to notify\n     * @return True if notification was sent or already sent for this block. Always returns true for address(0) without notifying.\n     */\n    function _notifyTarget(address target) private returns (bool) {\n        // Skip notification for zero address (default target when unset)\n        if (target == address(0)) return true;\n\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        AllocationTarget storage targetData = $.allocationTargets[target];\n\n        // Check-effects-interactions pattern: check if already notified this block\n        // solhint-disable-next-line gas-strict-inequalities\n        if (block.number <= targetData.lastChangeNotifiedBlock) return true;\n\n        // Effect: update the notification block before external calls\n        targetData.lastChangeNotifiedBlock = block.number;\n\n        // Interactions: make external call after state changes\n        // This will revert if the target's notification fails\n        IIssuanceTarget(target).beforeIssuanceAllocationChange();\n        return true;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     * @dev Implementation details:\n     * - The target will be notified at most once per block to prevent reentrancy looping\n     * - Will revert if target notification reverts\n     */\n    function notifyTarget(address target) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _notifyTarget(target);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     * @dev Implementation details:\n     * - This can be used to enable notification to be sent again (by setting to a past block) or to prevent notification until a future block (by setting to current or future block)\n     * - Returns the block number that was set, always equal to blockNumber in current implementation\n     */\n    function forceTargetNoChangeNotificationBlock(\n        address target,\n        uint256 blockNumber\n    ) external override onlyRole(GOVERNOR_ROLE) returns (uint256) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        AllocationTarget storage targetData = $.allocationTargets[target];\n\n        // Note: No bounds checking on blockNumber is intentional. Governance might need to set\n        // very high values in unanticipated edge cases or for recovery scenarios. Constraining\n        // governance flexibility is deemed unnecessary and perhaps counterproductive.\n        targetData.lastChangeNotifiedBlock = blockNumber;\n        return blockNumber;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setTargetAllocation(\n        IIssuanceTarget target,\n        uint256 allocatorMintingRate\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setTargetAllocation(address(target), allocatorMintingRate, 0, block.number);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setTargetAllocation(\n        IIssuanceTarget target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setTargetAllocation(address(target), allocatorMintingRate, selfMintingRate, block.number);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     * @dev Implementation details:\n     * - Requires distribution has reached at least minDistributedBlock issuance to change allocation\n     * - This allows configuration changes while paused by being deliberate about which block to distribute to\n     * - If the new allocations are the same as the current allocations, this function is a no-op\n     * - If both allocations are 0 and the target doesn't exist, this function is a no-op\n     * - If both allocations are 0 and the target exists, the target will be removed\n     * - If any allocation is non-zero and the target doesn't exist, the target will be added\n     * - Will revert if the total allocation would exceed available capacity (default target + current target allocation)\n     * - Will revert if attempting to add a target that doesn't support IIssuanceTarget\n     * @dev Self-minting targets must call getTargetIssuancePerBlock to determine their issuance and mint\n     * accordingly. See contract header for details on self-minting vs allocator-minting allocation.\n     */\n    function setTargetAllocation(\n        IIssuanceTarget target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate,\n        uint256 minDistributedBlock\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setTargetAllocation(address(target), allocatorMintingRate, selfMintingRate, minDistributedBlock);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setDefaultTarget(\n        address newAddress\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setDefaultTarget(newAddress, block.number);\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationAdministration\n     */\n    function setDefaultTarget(\n        address newAddress,\n        uint256 minDistributedBlock\n    ) external override onlyRole(GOVERNOR_ROLE) nonReentrant returns (bool) {\n        return _setDefaultTarget(newAddress, minDistributedBlock);\n    }\n\n    /**\n     * @notice Internal implementation for setting default target\n     * @param newAddress The address to set as the new default target\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return True if the value is applied (including if already the case), false if not applied due to paused state\n     * @dev The default target automatically receives the portion of issuance not allocated to other targets\n     * @dev This maintains the invariant that total allocation always equals issuancePerBlock\n     * @dev Reverts if attempting to set to an address that has a normal (non-default) allocation\n     * @dev Allocation data is copied from the old default to the new default, including lastChangeNotifiedBlock\n     * @dev No-op if setting to the same address\n     */\n    function _setDefaultTarget(address newAddress, uint256 minDistributedBlock) internal returns (bool) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        address oldAddress = $.targetAddresses[0];\n        if (newAddress == oldAddress) return true;\n\n        // Cannot set default target to a normally allocated target\n        // Check if newAddress is in targetAddresses (excluding index 0 which is the default)\n        // Note: This is O(n) for the number of targets, which could become expensive as targets increase.\n        // However, distribution operations already loop through all targets and\n        // would encounter gas issues first. Recovery mechanisms exist.\n        for (uint256 i = 1; i < $.targetAddresses.length; ++i) {\n            require($.targetAddresses[i] != newAddress, CannotSetDefaultToAllocatedTarget(newAddress));\n        }\n\n        if (_distributeIssuance() < minDistributedBlock) return false;\n\n        // Notify both old and new addresses of the allocation change\n        _notifyTarget(oldAddress);\n        _notifyTarget(newAddress);\n\n        // Preserve the notification block of newAddress before copying old address data\n        uint256 newAddressNotificationBlock = $.allocationTargets[newAddress].lastChangeNotifiedBlock;\n\n        // Update the default target at index 0\n        // This copies allocation data from old to new, including allocatorMintingRate and selfMintingRate\n        $.targetAddresses[0] = newAddress;\n        $.allocationTargets[newAddress] = $.allocationTargets[oldAddress];\n        delete $.allocationTargets[oldAddress];\n\n        // Restore the notification block for newAddress (regard as target-specific, not about default)\n        $.allocationTargets[newAddress].lastChangeNotifiedBlock = newAddressNotificationBlock;\n\n        emit DefaultTargetUpdated(oldAddress, newAddress);\n        return true;\n    }\n\n    /**\n     * @notice Internal implementation for setting target allocation\n     * @param target Address of the target to update\n     * @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate Self-minting rate for the target (tokens per block)\n     * @param minDistributedBlock Minimum block number that distribution must have reached\n     * @return True if the value is applied (including if already the case), false if not applied due to paused state\n     */\n    function _setTargetAllocation(\n        address target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate,\n        uint256 minDistributedBlock\n    ) internal returns (bool) {\n        if (!_validateAllocationChange(target, allocatorMintingRate, selfMintingRate)) return true;\n\n        if (_distributeIssuance() < minDistributedBlock) return false;\n\n        _notifyTarget(target);\n        _notifyTarget(_getIssuanceAllocatorStorage().targetAddresses[0]);\n\n        // Total allocation calculation and check is delayed until after notifications.\n        // Distributing and notifying unnecessarily is harmless, but we need to prevent\n        // reentrancy from looping and changing allocations mid-calculation.\n        // (Would not be likely to be exploitable due to only governor being able to\n        // make a call to set target allocation, but better to be paranoid.)\n        // Validate totals and auto-adjust default allocation BEFORE updating target data\n        // so we can read the old allocation values\n        _validateAndUpdateTotalAllocations(target, allocatorMintingRate, selfMintingRate);\n\n        // Then update the target's allocation data\n        _updateTargetAllocationData(target, allocatorMintingRate, selfMintingRate);\n\n        emit TargetAllocationUpdated(target, allocatorMintingRate, selfMintingRate);\n        return true;\n    }\n\n    /**\n     * @notice Validates allocation change for a target\n     * @param target Address of the target to validate\n     * @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate Self-minting rate for the target (tokens per block)\n     * @return True if validation passes and allocation change is needed, false if allocation is already set to these values\n     * @dev Reverts if target is address(0), default target, or doesn't support IIssuanceTarget (for non-zero rates)\n     */\n    function _validateAllocationChange(\n        address target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate\n    ) private view returns (bool) {\n        require(target != address(0), TargetAddressCannotBeZero());\n\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        require(target != $.targetAddresses[0], CannotSetAllocationForDefaultTarget($.targetAddresses[0]));\n\n        AllocationTarget storage targetData = $.allocationTargets[target];\n\n        if (targetData.allocatorMintingRate == allocatorMintingRate && targetData.selfMintingRate == selfMintingRate)\n            return false; // No change needed\n\n        if (allocatorMintingRate != 0 || selfMintingRate != 0)\n            require(\n                IERC165(target).supportsInterface(type(IIssuanceTarget).interfaceId),\n                TargetDoesNotSupportIIssuanceTarget(target)\n            );\n\n        return true;\n    }\n\n    /**\n     * @notice Updates global allocation totals and auto-adjusts default target to maintain 100% invariant\n     * @param target Address of the target being updated\n     * @param allocatorMintingRate New allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate New self-minting rate for the target (tokens per block)\n     * @dev The default target (at targetAddresses[0]) is automatically adjusted to ensure total allocation equals issuancePerBlock\n     * @dev This function is called BEFORE the target's allocation data has been updated so we can read old values\n     */\n    function _validateAndUpdateTotalAllocations(\n        address target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate\n    ) private {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        AllocationTarget storage targetData = $.allocationTargets[target];\n        AllocationTarget storage defaultTarget = $.allocationTargets[$.targetAddresses[0]];\n\n        // Calculations occur after notifications in the caller to prevent reentrancy issues\n\n        // availableRate comprises the default target's current allocator-minting rate,\n        // the target's current allocator-minting rate, and the target's current self-minting rate.\n        // This maintains the 100% allocation invariant by calculating how much can be reallocated\n        // to the target without exceeding total available allocation.\n        uint256 availableRate = defaultTarget.allocatorMintingRate +\n            targetData.allocatorMintingRate +\n            targetData.selfMintingRate;\n        require(\n            allocatorMintingRate + selfMintingRate <= availableRate, // solhint-disable-line gas-strict-inequalities\n            InsufficientAllocationAvailable(allocatorMintingRate + selfMintingRate, availableRate)\n        );\n\n        defaultTarget.allocatorMintingRate = availableRate - allocatorMintingRate - selfMintingRate;\n        $.totalSelfMintingRate = $.totalSelfMintingRate - targetData.selfMintingRate + selfMintingRate;\n    }\n\n    /**\n     * @notice Sets target allocation values and adds/removes target from active list\n     * @param target Address of the target being updated\n     * @param allocatorMintingRate New allocator-minting rate for the target (tokens per block)\n     * @param selfMintingRate New self-minting rate for the target (tokens per block)\n     * @dev This function is never called for the default target (at index 0), which is handled separately\n     */\n    function _updateTargetAllocationData(\n        address target,\n        uint256 allocatorMintingRate,\n        uint256 selfMintingRate\n    ) private {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        AllocationTarget storage targetData = $.allocationTargets[target];\n\n        // Internal design invariants:\n        // - targetAddresses[0] is always the default target and is never removed\n        // - targetAddresses[1..] contains all non-default targets with explicitly set non-zero allocations\n        // - targetAddresses does not contain duplicates\n        // - allocationTargets mapping contains allocation data for all targets in targetAddresses\n        // - default target is automatically adjusted by _validateAndUpdateTotalAllocations\n        // - Governance actions can create allocationTarget mappings with lastChangeNotifiedBlock set for targets not in targetAddresses. This is valid.\n        // Therefore:\n        // - Only add a non-default target to the list if it previously had no allocation\n        // - Remove a non-default target from the list when setting both allocations to 0\n        // - Delete allocationTargets mapping entry when removing a target from targetAddresses\n        // - Do not set lastChangeNotifiedBlock in this function\n        if (allocatorMintingRate != 0 || selfMintingRate != 0) {\n            // Add to list if previously had no allocation\n            if (targetData.allocatorMintingRate == 0 && targetData.selfMintingRate == 0) $.targetAddresses.push(target);\n\n            targetData.allocatorMintingRate = allocatorMintingRate;\n            targetData.selfMintingRate = selfMintingRate;\n        } else {\n            // Remove target completely (from list and mapping)\n            _removeTarget(target);\n        }\n    }\n\n    /**\n     * @notice Removes target from targetAddresses array and deletes its allocation data\n     * @param target Address of the target to remove\n     * @dev Starts at index 1 since index 0 is always the default target and should never be removed\n     * @dev Uses swap-and-pop for gas efficiency\n     */\n    function _removeTarget(address target) private {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        for (uint256 i = 1; i < $.targetAddresses.length; ++i) {\n            if ($.targetAddresses[i] == target) {\n                $.targetAddresses[i] = $.targetAddresses[$.targetAddresses.length - 1];\n                $.targetAddresses.pop();\n                delete $.allocationTargets[target];\n                break;\n            }\n        }\n    }\n\n    // -- View Functions --\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     */\n    function getIssuancePerBlock() external view override returns (uint256) {\n        return _getIssuanceAllocatorStorage().issuancePerBlock;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     */\n    function getDistributionState() external view override returns (DistributionState memory) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        return\n            DistributionState({\n                lastDistributionBlock: $.lastDistributionBlock,\n                lastSelfMintingBlock: $.lastSelfMintingBlock,\n                selfMintingOffset: $.selfMintingOffset\n            });\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     */\n    function getTargetCount() external view override returns (uint256) {\n        return _getIssuanceAllocatorStorage().targetAddresses.length;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     */\n    function getTargets() external view override returns (address[] memory) {\n        return _getIssuanceAllocatorStorage().targetAddresses;\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     */\n    function getTargetAt(uint256 index) external view override returns (address) {\n        return _getIssuanceAllocatorStorage().targetAddresses[index];\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationData\n     */\n    function getTargetData(address target) external view override returns (AllocationTarget memory) {\n        return _getIssuanceAllocatorStorage().allocationTargets[target];\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     * @dev Returns assigned allocation regardless of whether target is address(0) or the default.\n     * @dev For address(0), no minting occurs but the allocation represents the unallocated portion.\n     * @dev For effective allocations excluding unmintable portion, use getTotalAllocation().\n     */\n    function getTargetAllocation(address target) external view override returns (Allocation memory) {\n        AllocationTarget storage targetData = _getIssuanceAllocatorStorage().allocationTargets[target];\n        return\n            Allocation({\n                totalAllocationRate: targetData.allocatorMintingRate + targetData.selfMintingRate,\n                allocatorMintingRate: targetData.allocatorMintingRate,\n                selfMintingRate: targetData.selfMintingRate\n            });\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationDistribution\n     * @dev Returns assigned issuance rates regardless of whether target is address(0) or the default.\n     * @dev For address(0), no minting occurs but rates reflect what would be issued if mintable.\n     * @dev selfIssuanceBlockAppliedTo reflects the last block for which self-minting allowances have been\n     * calculated and emitted (lastSelfMintingBlock). This advances continuously, unaffected by pause state.\n     */\n    function getTargetIssuancePerBlock(address target) external view override returns (TargetIssuancePerBlock memory) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n        AllocationTarget storage targetData = $.allocationTargets[target];\n\n        return\n            TargetIssuancePerBlock({\n                allocatorIssuanceRate: targetData.allocatorMintingRate,\n                allocatorIssuanceBlockAppliedTo: $.lastDistributionBlock,\n                selfIssuanceRate: targetData.selfMintingRate,\n                selfIssuanceBlockAppliedTo: $.lastSelfMintingBlock\n            });\n    }\n\n    /**\n     * @inheritdoc IIssuanceAllocationStatus\n     * @dev For reporting purposes, if the default target is address(0), its allocation\n     * @dev is treated as \"unallocated\" since address(0) cannot receive minting.\n     * @dev When default is address(0): returns actual allocated amounts (may be less than issuancePerBlock)\n     * @dev When default is a real address: returns issuancePerBlock\n     * @dev Note: Internally, the contract always maintains 100% allocation invariant, even when default is address(0)\n     */\n    function getTotalAllocation() external view override returns (Allocation memory allocation) {\n        IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();\n\n        // If default is address(0), exclude its allocation from reported totals\n        // since it does not receive minting (so it is considered unallocated).\n        // Address(0) will only have non-zero allocation when it is the default target,\n        // so we can directly subtract zero address allocation.\n        allocation.totalAllocationRate = $.issuancePerBlock - $.allocationTargets[address(0)].allocatorMintingRate;\n        allocation.selfMintingRate = $.totalSelfMintingRate;\n        allocation.allocatorMintingRate = allocation.totalAllocationRate - allocation.selfMintingRate;\n    }\n}\n"
      },
      "project/contracts/common/BaseUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity 0.8.33;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport { AccessControlEnumerableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol\";\nimport { IGraphToken } from \"./IGraphToken.sol\";\nimport { IPausableControl } from \"@graphprotocol/interfaces/contracts/issuance/common/IPausableControl.sol\";\n\n/**\n * @title BaseUpgradeable\n * @author Edge & Node\n * @notice A base contract that provides role-based access control and pausability.\n *\n * @dev This contract combines OpenZeppelin's AccessControlEnumerable and Pausable\n * to provide a standardized way to manage access control and pausing functionality.\n * Using AccessControlEnumerable (rather than base AccessControl) enables on-chain\n * enumeration of role members via getRoleMemberCount() and getRoleMember(), which\n * is useful for deployment verification and auditing.\n * It uses ERC-7201 namespaced storage pattern for better storage isolation.\n * This contract is abstract and meant to be inherited by other contracts.\n * @custom:security-contact Please email security+contracts@thegraph.com if you find any bugs. We might have an active bug bounty program.\n */\nabstract contract BaseUpgradeable is\n    Initializable,\n    AccessControlEnumerableUpgradeable,\n    PausableUpgradeable,\n    IPausableControl\n{\n    // -- Constants --\n\n    /// @notice One million - used as the denominator for values provided as Parts Per Million (PPM)\n    /// @dev This constant represents 1,000,000 and serves as the denominator when working with\n    /// PPM values. For example, 50% would be represented as 500,000 PPM, calculated as\n    /// (500,000 / MILLION) = 0.5 = 50%\n    uint256 public constant MILLION = 1_000_000;\n\n    // -- Role Constants --\n\n    /**\n     * @notice Role identifier for governor accounts\n     * @dev Governors have the highest level of access and can:\n     * - Grant and revoke roles within the established hierarchy\n     * - Perform administrative functions and system configuration\n     * - Set critical parameters and upgrade contracts\n     * Admin of: GOVERNOR_ROLE, PAUSE_ROLE, OPERATOR_ROLE\n     */\n    bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n    /**\n     * @notice Role identifier for pause accounts\n     * @dev Pause role holders can:\n     * - Pause and unpause contract operations for emergency situations\n     * Typically granted to automated monitoring systems or emergency responders.\n     * Pausing is intended for quick response to potential threats, and giving time for investigation and resolution (potentially with governance intervention).\n     * Admin: GOVERNOR_ROLE\n     */\n    bytes32 public constant PAUSE_ROLE = keccak256(\"PAUSE_ROLE\");\n\n    /**\n     * @notice Role identifier for operator accounts\n     * @dev Operators can:\n     * - Perform operational tasks as defined by inheriting contracts\n     * - Manage roles that are designated as operator-administered\n     * Admin: GOVERNOR_ROLE\n     */\n    bytes32 public constant OPERATOR_ROLE = keccak256(\"OPERATOR_ROLE\");\n\n    // -- Immutable Variables --\n\n    /// @notice The Graph Token contract\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    IGraphToken internal immutable GRAPH_TOKEN;\n\n    // -- Custom Errors --\n\n    /// @notice Thrown when attempting to set the Graph Token to the zero address\n    error GraphTokenCannotBeZeroAddress();\n\n    /// @notice Thrown when attempting to set the governor to the zero address\n    error GovernorCannotBeZeroAddress();\n\n    // -- Constructor --\n\n    /**\n     * @notice Constructor for the BaseUpgradeable contract\n     * @dev This contract is upgradeable, but we use the constructor to set immutable variables\n     * and disable initializers to prevent the implementation contract from being initialized.\n     * @param graphToken Address of the Graph Token contract\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(address graphToken) {\n        require(graphToken != address(0), GraphTokenCannotBeZeroAddress());\n        GRAPH_TOKEN = IGraphToken(graphToken);\n        _disableInitializers();\n    }\n\n    // -- Initialization --\n\n    // solhint-disable-next-line func-name-mixedcase\n    // forge-lint: disable-next-item(mixed-case-function)\n    /**\n     * @notice Internal function to initialize the BaseUpgradeable contract\n     * @dev This function is used by child contracts to initialize the BaseUpgradeable contract\n     * @param governor Address that will have the GOVERNOR_ROLE\n     */\n    function __BaseUpgradeable_init(address governor) internal {\n        __AccessControlEnumerable_init();\n        __Pausable_init();\n\n        __BaseUpgradeable_init_unchained(governor);\n    }\n\n    /**\n     * @notice Internal unchained initialization function for BaseUpgradeable\n     * @dev This function sets up the governor role and role admin hierarchy\n     * @param governor Address that will have the GOVERNOR_ROLE\n     */\n    // forge-lint: disable-next-line(mixed-case-function)\n    function __BaseUpgradeable_init_unchained(address governor) internal {\n        // solhint-disable-previous-line func-name-mixedcase\n\n        require(governor != address(0), GovernorCannotBeZeroAddress());\n\n        // Set up role admin hierarchy:\n        // GOVERNOR is admin of GOVERNOR, PAUSE, and OPERATOR roles\n        _setRoleAdmin(GOVERNOR_ROLE, GOVERNOR_ROLE);\n        _setRoleAdmin(PAUSE_ROLE, GOVERNOR_ROLE);\n        _setRoleAdmin(OPERATOR_ROLE, GOVERNOR_ROLE);\n\n        // Grant initial governor role\n        _grantRole(GOVERNOR_ROLE, governor);\n    }\n\n    // -- External Functions --\n\n    /**\n     * @inheritdoc IPausableControl\n     */\n    function pause() external override onlyRole(PAUSE_ROLE) {\n        _pause();\n    }\n\n    /**\n     * @inheritdoc IPausableControl\n     */\n    function unpause() external override onlyRole(PAUSE_ROLE) {\n        _unpause();\n    }\n\n    /**\n     * @inheritdoc IPausableControl\n     */\n    function paused() public view virtual override(PausableUpgradeable, IPausableControl) returns (bool) {\n        return super.paused();\n    }\n\n    /**\n     * @notice Check if this contract supports a given interface\n     * @dev Adds support for IPausableControl interface\n     * @param interfaceId The interface identifier to check\n     * @return True if the contract supports the interface, false otherwise\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IPausableControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n"
      },
      "project/contracts/common/IGraphToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title IGraphToken\n * @author Edge & Node\n * @notice Minimal interface for the Graph Token contract used by issuance contracts\n * @dev Extends IERC20 with mint capability. This interface is compatible with OZ 5.x.\n */\ninterface IGraphToken is IERC20 {\n    /**\n     * @notice Mints new tokens to a specified account\n     * @dev Only callable by accounts with minter role\n     * @param to The account to mint tokens to\n     * @param amount The amount of tokens to mint\n     */\n    function mint(address to, uint256 amount) external;\n}\n"
      },
      "project/contracts/eligibility/RewardsEligibilityOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity 0.8.33;\n\nimport { IRewardsEligibility } from \"@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibility.sol\";\nimport { IRewardsEligibilityAdministration } from \"@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityAdministration.sol\";\nimport { IRewardsEligibilityReporting } from \"@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityReporting.sol\";\nimport { IRewardsEligibilityStatus } from \"@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityStatus.sol\";\nimport { BaseUpgradeable } from \"../common/BaseUpgradeable.sol\";\n\n/**\n * @title RewardsEligibilityOracle\n * @author Edge & Node\n * @notice This contract allows authorized oracles to mark indexers as eligible to receive rewards\n * with an expiration mechanism. Under normal configuration with reasonable eligibility periods, indexers\n * are denied by default until they are explicitly marked as eligible, and their eligibility expires after\n * a configurable eligibility period. The contract also includes a global eligibility check toggle and an\n * oracle update timeout mechanism.\n * @dev Note: If the eligibility period is set to an extremely large value that exceeds the current\n * block timestamp, all indexers (including those never registered) will be eligible.\n * @custom:security-contact Please email security+contracts@thegraph.com if you find any bugs. We might have an active bug bounty program.\n * @custom:security-warning Configuration changes (eligibility period, validation toggle) can create race\n * conditions with in-flight reward claim transactions. When configuration changes make an indexer ineligible\n * between transaction submission and execution, the indexer permanently loses those rewards.\n * Operators should announce configuration changes in advance and consider implementing\n * a two-step process (announce delay, then execute) for changes that reduce eligibility.\n */\ncontract RewardsEligibilityOracle is\n    BaseUpgradeable,\n    IRewardsEligibility,\n    IRewardsEligibilityAdministration,\n    IRewardsEligibilityReporting,\n    IRewardsEligibilityStatus\n{\n    // -- Role Constants --\n\n    /**\n     * @notice Oracle role identifier\n     * @dev Oracle role holders can:\n     * - Mark indexers as eligible to receive rewards (based on off-chain quality assessment)\n     * This role is typically granted to automated quality assessment systems\n     * Admin: OPERATOR_ROLE (operators can manage oracle roles)\n     */\n    bytes32 public constant ORACLE_ROLE = keccak256(\"ORACLE_ROLE\");\n    // -- Namespaced Storage --\n\n    /// @notice ERC-7201 storage location for RewardsEligibilityOracle\n    bytes32 private constant REWARDS_ELIGIBILITY_ORACLE_STORAGE_LOCATION =\n        // Not needed for compile time calculation\n        // solhint-disable-next-line gas-small-strings\n        keccak256(abi.encode(uint256(keccak256(\"graphprotocol.storage.RewardsEligibilityOracle\")) - 1)) &\n            ~bytes32(uint256(0xff));\n\n    /// @notice Main storage structure for RewardsEligibilityOracle using ERC-7201 namespaced storage\n    /// @param indexerEligibilityTimestamps Mapping of indexers to their eligibility renewal timestamps\n    /// @param eligibilityPeriod Period in seconds for which indexer eligibility status lasts\n    /// @param eligibilityValidationEnabled Flag to enable/disable eligibility validation\n    /// @param oracleUpdateTimeout Timeout period in seconds after which isEligible returns true if no oracle updates\n    /// @param lastOracleUpdateTime Timestamp of the last oracle update\n    /// @custom:storage-location erc7201:graphprotocol.storage.RewardsEligibilityOracle\n    struct RewardsEligibilityOracleData {\n        /// @dev Mapping of indexers to their eligibility renewal timestamps\n        mapping(address => uint256) indexerEligibilityTimestamps;\n        /// @dev Period in seconds for which indexer eligibility status lasts\n        uint256 eligibilityPeriod;\n        /// @dev Flag to enable/disable eligibility validation\n        bool eligibilityValidationEnabled;\n        /// @dev Timeout period in seconds after which isEligible returns true if no oracle updates\n        uint256 oracleUpdateTimeout;\n        /// @dev Timestamp of the last oracle update\n        uint256 lastOracleUpdateTime;\n    }\n\n    /**\n     * @notice Returns the storage struct for RewardsEligibilityOracle\n     * @return $ contract storage\n     */\n    function _getRewardsEligibilityOracleStorage() private pure returns (RewardsEligibilityOracleData storage $) {\n        // solhint-disable-previous-line use-natspec\n        // Solhint does not support $ return variable in natspec\n        bytes32 slot = REWARDS_ELIGIBILITY_ORACLE_STORAGE_LOCATION;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := slot\n        }\n    }\n\n    // -- Constructor --\n\n    /**\n     * @notice Constructor for the RewardsEligibilityOracle contract\n     * @dev This contract is upgradeable, but we use the constructor to pass the Graph Token address\n     * to the base contract.\n     * @param graphToken Address of the Graph Token contract\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(address graphToken) BaseUpgradeable(graphToken) {}\n\n    // -- Initialization --\n\n    /**\n     * @notice Initialize the RewardsEligibilityOracle contract\n     * @param governor Address that will have the GOVERNOR_ROLE\n     * @dev Also sets OPERATOR as admin of ORACLE role\n     */\n    function initialize(address governor) external virtual initializer {\n        __BaseUpgradeable_init(governor);\n\n        // OPERATOR is admin of ORACLE role\n        _setRoleAdmin(ORACLE_ROLE, OPERATOR_ROLE);\n\n        // Set default values\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n        $.eligibilityPeriod = 14 days;\n        $.oracleUpdateTimeout = 7 days;\n        $.eligibilityValidationEnabled = false; // Start with eligibility validation disabled, to be enabled later when the oracle is ready\n    }\n\n    /**\n     * @notice Check if this contract supports a given interface\n     * @dev Overrides the supportsInterface function from ERC165Upgradeable\n     * @param interfaceId The interface identifier to check\n     * @return True if the contract supports the interface, false otherwise\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IRewardsEligibility).interfaceId ||\n            interfaceId == type(IRewardsEligibilityAdministration).interfaceId ||\n            interfaceId == type(IRewardsEligibilityReporting).interfaceId ||\n            interfaceId == type(IRewardsEligibilityStatus).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    // -- Governance Functions --\n\n    /**\n     * @notice Set the eligibility period for indexers\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param eligibilityPeriod New eligibility period in seconds\n     * @return True if the state is as requested (eligibility period is set to the specified value)\n     * @custom:warning Configuration changes can affect in-flight reward claim transactions. Reducing the\n     * eligibility period may cause indexers to lose rewards if their claim transactions execute after\n     * they become ineligible due to the configuration change. Consider announcing configuration changes\n     * in advance and using a two-step process (announce, then execute) for changes that reduce eligibility.\n     */\n    function setEligibilityPeriod(uint256 eligibilityPeriod) external override onlyRole(OPERATOR_ROLE) returns (bool) {\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n        uint256 oldEligibilityPeriod = $.eligibilityPeriod;\n\n        if (eligibilityPeriod != oldEligibilityPeriod) {\n            $.eligibilityPeriod = eligibilityPeriod;\n            emit EligibilityPeriodUpdated(oldEligibilityPeriod, eligibilityPeriod);\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice Set the oracle update timeout\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param oracleUpdateTimeout New timeout period in seconds\n     * @return True if the state is as requested (timeout is set to the specified value)\n     */\n    function setOracleUpdateTimeout(\n        uint256 oracleUpdateTimeout\n    ) external override onlyRole(OPERATOR_ROLE) returns (bool) {\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n        uint256 oldTimeout = $.oracleUpdateTimeout;\n\n        if (oracleUpdateTimeout != oldTimeout) {\n            $.oracleUpdateTimeout = oracleUpdateTimeout;\n            emit OracleUpdateTimeoutUpdated(oldTimeout, oracleUpdateTimeout);\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice Set eligibility validation state\n     * @dev Only callable by accounts with the OPERATOR_ROLE\n     * @param enabled True to enable eligibility validation, false to disable\n     * @return True if successfully set (always the case for current code)\n     * @custom:warning Enabling eligibility validation can affect in-flight reward claim transactions.\n     * Indexers who submitted claim transactions while validation was disabled may lose rewards if\n     * validation is enabled before their transactions execute and they are not marked as eligible.\n     * Consider announcing this change in advance to allow indexers to adjust their claiming behavior.\n     */\n    function setEligibilityValidation(bool enabled) external override onlyRole(OPERATOR_ROLE) returns (bool) {\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n\n        if ($.eligibilityValidationEnabled != enabled) {\n            $.eligibilityValidationEnabled = enabled;\n            emit EligibilityValidationUpdated(enabled);\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice Renew eligibility for provided indexers to receive rewards\n     * @param indexers Array of indexer addresses. Zero addresses are ignored.\n     * @param data Arbitrary calldata for future extensions\n     * @return Number of indexers whose eligibility renewal timestamp was updated\n     */\n    function renewIndexerEligibility(\n        address[] calldata indexers,\n        bytes calldata data\n    ) external override onlyRole(ORACLE_ROLE) returns (uint256) {\n        emit IndexerEligibilityData(msg.sender, data);\n\n        uint256 updatedCount = 0;\n        uint256 blockTimestamp = block.timestamp;\n\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n        $.lastOracleUpdateTime = blockTimestamp;\n\n        // Update each indexer's eligible timestamp\n        for (uint256 i = 0; i < indexers.length; ++i) {\n            address indexer = indexers[i];\n\n            if (indexer != address(0) && $.indexerEligibilityTimestamps[indexer] < blockTimestamp) {\n                $.indexerEligibilityTimestamps[indexer] = blockTimestamp;\n                emit IndexerEligibilityRenewed(indexer, msg.sender);\n                ++updatedCount;\n            }\n        }\n\n        return updatedCount;\n    }\n\n    // -- View Functions --\n\n    /**\n     * @inheritdoc IRewardsEligibility\n     * @dev Returns true if any of the following conditions are met:\n     * 1. Eligibility validation is disabled globally\n     * 2. Oracle timeout has been exceeded (fail-safe to allow all indexers)\n     * 3. block.timestamp < indexerEligibilityTimestamps[indexer] + eligibilityPeriod\n     *\n     * Note on condition 3: For indexers who have never been registered, indexerEligibilityTimestamps[indexer]\n     * is 0. If eligibilityPeriod is set to an extremely large value exceeding block.timestamp, the check\n     * becomes (block.timestamp < 0 + eligibilityPeriod), which will be true, making all indexers eligible.\n     */\n    function isEligible(address indexer) external view override returns (bool) {\n        RewardsEligibilityOracleData storage $ = _getRewardsEligibilityOracleStorage();\n\n        // If eligibility validation is disabled, treat all indexers as eligible\n        if (!$.eligibilityValidationEnabled) return true;\n\n        // If no oracle updates have been made for oracleUpdateTimeout, treat all indexers as eligible\n        if ($.lastOracleUpdateTime + $.oracleUpdateTimeout < block.timestamp) return true;\n\n        return block.timestamp < $.indexerEligibilityTimestamps[indexer] + $.eligibilityPeriod;\n    }\n\n    /**\n     * @notice Get the last eligibility renewal timestamp for an indexer\n     * @param indexer Address of the indexer\n     * @return The last eligibility renewal timestamp, or 0 if the indexer's eligibility has never been renewed\n     */\n    function getEligibilityRenewalTime(address indexer) external view override returns (uint256) {\n        return _getRewardsEligibilityOracleStorage().indexerEligibilityTimestamps[indexer];\n    }\n\n    /**\n     * @notice Get the eligibility period\n     * @return The current eligibility period in seconds\n     */\n    function getEligibilityPeriod() external view override returns (uint256) {\n        return _getRewardsEligibilityOracleStorage().eligibilityPeriod;\n    }\n\n    /**\n     * @notice Get the oracle update timeout\n     * @return The current oracle update timeout in seconds\n     */\n    function getOracleUpdateTimeout() external view override returns (uint256) {\n        return _getRewardsEligibilityOracleStorage().oracleUpdateTimeout;\n    }\n\n    /**\n     * @notice Get the last oracle update time\n     * @return The timestamp of the last oracle update\n     */\n    function getLastOracleUpdateTime() external view override returns (uint256) {\n        return _getRewardsEligibilityOracleStorage().lastOracleUpdateTime;\n    }\n\n    /**\n     * @notice Get eligibility validation state\n     * @return True if eligibility validation is enabled, false otherwise\n     */\n    function getEligibilityValidation() external view override returns (bool) {\n        return _getRewardsEligibilityOracleStorage().eligibilityValidationEnabled;\n    }\n}\n"
      },
      "project/contracts/test/allocate/IssuanceAllocatorTestHarness.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity 0.8.33;\n\nimport { IssuanceAllocator } from \"../../allocate/IssuanceAllocator.sol\";\n\n/**\n * @title IssuanceAllocatorTestHarness\n * @author Edge & Node\n * @notice Test harness to expose internal functions for white-box testing\n * @dev This contract allows direct testing of internal distribution functions to achieve 100% coverage\n */\ncontract IssuanceAllocatorTestHarness is IssuanceAllocator {\n    /**\n     * @notice Constructor for the test harness\n     * @param _graphToken Address of the Graph Token contract\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(address _graphToken) IssuanceAllocator(_graphToken) {}\n\n    /**\n     * @notice Exposes _distributePendingProportionally for testing\n     * @dev Allows testing of defensive checks and edge cases\n     * @param available Total available allocator-minting budget for the period\n     * @param allocatedRate Total rate allocated to non-default targets\n     * @param toBlockNumber Block number distributing to\n     */\n    function exposedDistributePendingProportionally(\n        uint256 available,\n        uint256 allocatedRate,\n        uint256 toBlockNumber\n    ) external {\n        _distributePendingProportionally(available, allocatedRate, toBlockNumber);\n    }\n\n    /**\n     * @notice Exposes _distributePendingWithFullRate for testing\n     * @dev Allows testing of edge cases in full rate distribution\n     * @param blocks Number of blocks in the distribution period\n     * @param available Total available allocator-minting budget for the period\n     * @param allocatedTotal Total amount allocated to non-default targets at full rate\n     * @param toBlockNumber Block number distributing to\n     */\n    function exposedDistributePendingWithFullRate(\n        uint256 blocks,\n        uint256 available,\n        uint256 allocatedTotal,\n        uint256 toBlockNumber\n    ) external {\n        _distributePendingWithFullRate(blocks, available, allocatedTotal, toBlockNumber);\n    }\n}\n"
      },
      "project/contracts/test/allocate/MockERC165.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.27;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title MockERC165\n * @author Edge & Node\n * @dev Minimal implementation of IERC165 for testing\n * @notice Used to test interface validation - supports only ERC165, not specific interfaces\n */\ncontract MockERC165 is IERC165 {\n    /**\n     * @inheritdoc IERC165\n     */\n    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "project/contracts/test/allocate/MockNotificationTracker.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @title MockNotificationTracker\n * @author Edge & Node\n * @notice A mock contract that tracks notification calls for testing\n * @dev Records when beforeIssuanceAllocationChange is called\n */\ncontract MockNotificationTracker is IIssuanceTarget, ERC165 {\n    /// @notice Number of times the contract has been notified\n    uint256 public notificationCount;\n\n    /// @notice Block number of the last notification received\n    uint256 public lastNotificationBlock;\n\n    /// @notice Emitted when a notification is received\n    /// @param blockNumber The block number when notification was received\n    /// @param count The total notification count after this notification\n    event NotificationReceived(uint256 indexed blockNumber, uint256 indexed count); // solhint-disable-line gas-indexed-events\n\n    /// @inheritdoc IIssuanceTarget\n    function beforeIssuanceAllocationChange() external override {\n        ++notificationCount;\n        lastNotificationBlock = block.number;\n        emit NotificationReceived(block.number, notificationCount);\n    }\n\n    /// @inheritdoc IIssuanceTarget\n    function setIssuanceAllocator(address _issuanceAllocator) external pure override {}\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IIssuanceTarget).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// @notice Resets the notification counter and last block to zero\n    function resetNotificationCount() external {\n        notificationCount = 0;\n        lastNotificationBlock = 0;\n    }\n}\n"
      },
      "project/contracts/test/allocate/MockReentrantTarget.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { IIssuanceAllocationDistribution } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationDistribution.sol\";\nimport { IIssuanceAllocationAdministration } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocationAdministration.sol\";\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @title MockReentrantTarget\n * @author Edge & Node\n * @notice A malicious mock contract that attempts reentrancy attacks for testing\n * @dev Used for testing reentrancy protection in IssuanceAllocator\n */\ncontract MockReentrantTarget is IIssuanceTarget, ERC165 {\n    /// @notice The issuance allocator to target for reentrancy attacks\n    address public issuanceAllocator;\n    /// @notice The configured reentrancy action to perform\n    ReentrantAction public actionToPerform;\n    /// @notice Whether reentrancy should be attempted\n    bool public shouldAttemptReentrancy;\n\n    enum ReentrantAction {\n        None,\n        DistributeIssuance,\n        SetTargetAllocation1Param,\n        SetTargetAllocation2Param,\n        SetTargetAllocation3Param,\n        SetIssuancePerBlock,\n        SetIssuancePerBlock2Param,\n        NotifyTarget,\n        SetDefaultTarget1Param,\n        SetDefaultTarget2Param,\n        DistributePendingIssuance0Param,\n        DistributePendingIssuance1Param\n    }\n\n    /// @notice Sets the action to perform during reentrancy attempt\n    /// @param _action The reentrancy action to configure\n    function setReentrantAction(ReentrantAction _action) external {\n        actionToPerform = _action;\n        shouldAttemptReentrancy = _action != ReentrantAction.None;\n    }\n\n    /// @inheritdoc IIssuanceTarget\n    function beforeIssuanceAllocationChange() external override {\n        if (!shouldAttemptReentrancy) return;\n\n        // Attempt reentrancy based on configured action\n        if (actionToPerform == ReentrantAction.DistributeIssuance) {\n            IIssuanceAllocationDistribution(issuanceAllocator).distributeIssuance();\n        } else if (actionToPerform == ReentrantAction.SetTargetAllocation1Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setTargetAllocation(\n                IIssuanceTarget(address(this)),\n                1000\n            );\n        } else if (actionToPerform == ReentrantAction.SetTargetAllocation2Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setTargetAllocation(\n                IIssuanceTarget(address(this)),\n                1000,\n                0\n            );\n        } else if (actionToPerform == ReentrantAction.SetTargetAllocation3Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setTargetAllocation(\n                IIssuanceTarget(address(this)),\n                1000,\n                0,\n                block.number\n            );\n        } else if (actionToPerform == ReentrantAction.SetIssuancePerBlock) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setIssuancePerBlock(1000);\n        } else if (actionToPerform == ReentrantAction.SetIssuancePerBlock2Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setIssuancePerBlock(1000, block.number);\n        } else if (actionToPerform == ReentrantAction.NotifyTarget) {\n            IIssuanceAllocationAdministration(issuanceAllocator).notifyTarget(address(this));\n        } else if (actionToPerform == ReentrantAction.SetDefaultTarget1Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setDefaultTarget(address(this));\n        } else if (actionToPerform == ReentrantAction.SetDefaultTarget2Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).setDefaultTarget(address(this), block.number);\n        } else if (actionToPerform == ReentrantAction.DistributePendingIssuance0Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).distributePendingIssuance();\n        } else if (actionToPerform == ReentrantAction.DistributePendingIssuance1Param) {\n            IIssuanceAllocationAdministration(issuanceAllocator).distributePendingIssuance(block.number);\n        }\n    }\n\n    /// @inheritdoc IIssuanceTarget\n    function setIssuanceAllocator(address _issuanceAllocator) external override {\n        issuanceAllocator = _issuanceAllocator;\n    }\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IIssuanceTarget).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n"
      },
      "project/contracts/test/allocate/MockRevertingTarget.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @title MockRevertingTarget\n * @author Edge & Node\n * @notice A mock contract that reverts when beforeIssuanceAllocationChange is called\n * @dev Used for testing error handling in IssuanceAllocator\n */\ncontract MockRevertingTarget is IIssuanceTarget, ERC165 {\n    /// @notice Error thrown when the target reverts intentionally\n    error TargetRevertsIntentionally();\n    /**\n     * @inheritdoc IIssuanceTarget\n     */\n    function beforeIssuanceAllocationChange() external pure override {\n        revert TargetRevertsIntentionally();\n    }\n\n    /**\n     * @inheritdoc IIssuanceTarget\n     */\n    function setIssuanceAllocator(address _issuanceAllocator) external pure override {\n        // No-op\n    }\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IIssuanceTarget).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n"
      },
      "project/contracts/test/allocate/MockSimpleTarget.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport { IIssuanceTarget } from \"@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol\";\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @title MockSimpleTarget\n * @author Edge & Node\n * @notice A simple mock contract that implements IIssuanceTarget for testing\n * @dev Used for testing basic functionality in IssuanceAllocator\n */\ncontract MockSimpleTarget is IIssuanceTarget, ERC165 {\n    /// @inheritdoc IIssuanceTarget\n    function beforeIssuanceAllocationChange() external pure override {}\n\n    /// @inheritdoc IIssuanceTarget\n    function setIssuanceAllocator(address _issuanceAllocator) external pure override {}\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IIssuanceTarget).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n"
      }
    }
  }
}