{"file_path":"contracts/core/CoverOrderAllocator.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {MerkleProof} from \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport {Checkpoints} from \"@openzeppelin/contracts/utils/structs/Checkpoints.sol\";\nimport {EnumerableSet} from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport {IFirelightVault} from \"./interfaces/IFirelightVault.sol\";\nimport {ICoverOrderAllocator} from \"./interfaces/ICoverOrderAllocator.sol\";\nimport {IAggregatorV3} from \"./interfaces/IAggregatorV3.sol\";\nimport {PriceFeed} from \"./lib/PriceFeed.sol\";\nimport {Decimals} from \"./lib/Decimals.sol\";\nimport {CoverNFT} from \"./CoverNFT.sol\";\n\n/**\n * @title CoverOrderAllocator\n * @notice Manages the cover order lifecycle and applies off-chain matching results on-chain.\n * Curators create cover orders for the next period; an off-chain engine matches them against\n * available capacity and submits the result as a Merkle commitment. Orders are then settled\n * individually against that commitment, charging premium, minting a CoverNFT, and recording\n * per-market allocations used later by the IncidentManager for payouts.\n *\n * All monetary values are held in a canonical USD unit; conversion to/from each\n * token's native decimals happens only at transfer boundaries. See {ICoverOrderAllocator} for\n * the full decimal convention, matching flow, and Merkle leaf encoding.\n *\n * Capacity is recomputed on-chain at commit/recommit from the first-loss buffer balance plus\n * oracle-priced staked assets, scaled by leverage/minCAR, and widened by the per-period\n * `divergenceToleranceBps` to absorb price/buffer drift between the off-chain snapshot and\n * commit inclusion. The same effective capacity bounds both total allocation and per-protocol\n * concentration caps.\n *\n * Order status flow:\n * - `PENDING` -> `MATCHED` or `PARTIAL` on settle.\n * - `PENDING` -> `CANCELLED` via curator cancel or the permissionless expired-order sweep.\n *\n * Role responsibilities:\n * - `DEFAULT_ADMIN_ROLE`: manages role assignments.\n * - `ADMIN_ROLE`: updates the premium collector, price feed adapter, and max price age.\n * - `CURATOR_ROLE`: creates and cancels cover orders.\n * - `ALLOCATOR_ROLE`: commits matching results and settles orders.\n * - `CONFIG_ADMIN_ROLE`: manages markets, premium tokens, concentration caps, capacity config,\n *   the settlement grace period, and recommits.\n * @custom:security-contact securityreport@firelight.finance\n */\ncontract CoverOrderAllocator is ICoverOrderAllocator, AccessControlUpgradeable, ReentrancyGuardUpgradeable {\n    using SafeERC20 for IERC20;\n    using Math for uint256;\n    // 32 bits for period 224 for configId\n    using Checkpoints for Checkpoints.Trace224;\n    using EnumerableSet for EnumerableSet.AddressSet;\n    using PriceFeed for IAggregatorV3;\n\n    // --- Roles ---\n    /// @notice Role allowed to create and cancel cover orders.\n    bytes32 public constant CURATOR_ROLE = keccak256(\"CURATOR_ROLE\");\n    /// @notice Role allowed to commit matching results and settle orders.\n    bytes32 public constant ALLOCATOR_ROLE = keccak256(\"ALLOCATOR_ROLE\");\n    /// @notice Role allowed to manage markets, premium tokens, concentration caps, capacity\n    ///         config, the settlement grace period, and recommits.\n    bytes32 public constant CONFIG_ADMIN_ROLE = keccak256(\"CONFIG_ADMIN_ROLE\");\n    /// @notice Role allowed to update the premium collector, price feed adapter, and max price age.\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN_ROLE\");\n\n    // --- Constants ---\n    /// @notice Canonical decimals used for all on-chain monetary values.\n    uint8 public constant CANONICAL_DECIMALS = 18;\n    uint256 private constant SECONDS_PER_YEAR = 365 days;\n    uint256 private constant BPS_DENOMINATOR = 10_000;\n    // Hard ceiling for `CapacityConfig.divergenceToleranceBps`. Kept small: the tolerance\n    // is accepted under-collateralization vs the CAR target, only meant to absorb the\n    // price/FLB drift between the off-chain matcher snapshot and commit inclusion.\n    uint16 private constant MAX_DIVERGENCE_TOLERANCE_BPS = 1_000; // 10%\n    // Cap on `effectiveLeverage` relative to `minCAR`. Real backing behind sold cover is\n    // `minCAR / (effectiveLeverage × (1 + tolerance))`, so bounding the ratio floors it at\n    // `1 / (MAX_LEVERAGE_FACTOR × (1 + tolerance))` regardless of the configured `minCAR`.\n    uint256 private constant MAX_LEVERAGE_FACTOR = 5;\n    // Keep governance-set CAR targets within the risk policy's approved operating range.\n    uint256 private constant MIN_CAR_BPS = 12_000;\n    uint256 private constant MAX_CAR_BPS = 50_000;\n    // Hard ceiling for `settlementGracePeriod`. Keeps the grace from consuming the settle\n    // window: settlement requires the grace elapsed AND the order's period still current.\n    // The vault enforces every period duration to be a multiple of SMALLEST_PERIOD_DURATION\n    // (1 day), so this bound is at most a third of any period under any future schedule.\n    uint48 private constant MAX_GRACE_PERIOD = 8 hours;\n\n    // --- ERC-7201 Namespaced Storage ---\n    /// @custom:storage-location erc7201:firelight.coverorderallocator.storage\n    struct CoverOrderAllocatorStorage {\n        IFirelightVault vault;\n        address premiumCollector;\n        CoverNFT coverNFT;\n        uint256 nextCoverOrderId;\n        mapping(uint256 coverOrderId => CoverOrder) orders;\n        mapping(uint256 coverOrderId => MarketAllocation[]) orderMarkets;\n        mapping(bytes32 marketId => Market) supportedMarkets;\n        EnumerableSet.AddressSet supportedPremiumTokens;\n        CapacityConfig[] capacityConfigHistory;\n        Checkpoints.Trace224 capacityConfigCheckpoints; // period => index in capacityConfigHistory\n        mapping(uint256 period => AllocationCommitment) allocationCommitments;\n        mapping(uint256 period => uint256[]) ordersIdByPeriod;\n        mapping(uint256 period => mapping(bytes32 protocolConcentrationHash => uint256)) protocolConcentrationSettledCover;\n        bytes32[] supportedMarketIds;\n        mapping(bytes32 protocolConcentrationHash => Checkpoints.Trace224) protocolConcentrationCheckpoints;\n        bytes32[] supportedProtocolConcentrationHashes;\n        mapping(bytes32 protocolConcentrationHash => ProtocolConcentration) protocolConcentrations;\n        // Cached `decimals()` of each registered premium token and the vault asset.\n        // Populated on registration; read on hot paths to avoid per-call STATICCALLs.\n        // The first-loss-buffer token lives inside `CapacityConfig` (checkpointed\n        // per period) and its decimals are read on-demand in `commitAllocation`.\n        mapping(address token => uint8) premiumTokenDecimals;\n        uint8 vaultAssetDecimals;\n        // Vault-asset USD oracle. Read on `commitAllocation` to value staked assets.\n        IAggregatorV3 priceFeedAdapter;\n        uint48 maxPriceAge;\n        uint8 priceFeedDecimals;\n        uint48 settlementGracePeriod;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"firelight.coverorderallocator.storage\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant STORAGE_LOCATION = 0x89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd000;\n\n    function _getStorage() private pure returns (CoverOrderAllocatorStorage storage $) {\n        assembly {\n            $.slot := STORAGE_LOCATION\n        }\n    }\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        // Disable initializers on the implementation following the best practices\n        _disableInitializers();\n    }\n\n    /// @notice Initializes dependencies, roles, premium tokens, markets, concentration caps,\n    ///         and the initial capacity configuration.\n    /// @param params Initialization parameters; see {ICoverOrderAllocator.InitParams}.\n    function initialize(InitParams calldata params) external initializer {\n        _requireNonZero(address(params.vault));\n        _requireNonZero(address(params.coverNFT));\n        _requireNonZero(params.admin);\n        _requireNonZero(params.adminRole);\n        _requireNonZero(params.curatorRole);\n        _requireNonZero(params.allocatorRole);\n        _requireNonZero(params.configAdminRole);\n\n        __AccessControl_init();\n        __ReentrancyGuard_init();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        $.vault = params.vault;\n        $.coverNFT = params.coverNFT;\n\n        $.vaultAssetDecimals = _readDecimals(params.vault.asset());\n\n        _setPremiumCollector(params.premiumCollector);\n        _setMaxPriceAge(params.maxPriceAge);\n        _setPriceFeedAdapter(params.priceFeedAdapter);\n\n        for (uint256 i; i < params.premiumTokens.length; ++i) {\n            _addSupportedPremiumToken(params.premiumTokens[i]);\n        }\n\n        for (uint256 i; i < params.initialProtocolConcentrations.length; ++i) {\n            _setProtocolConcentration(params.initialProtocolConcentrations[i]);\n        }\n\n        for (uint256 i; i < params.newMarkets.length; ++i) {\n            _addSupportedMarket(params.newMarkets[i]);\n        }\n\n        _setCapacityConfig(params.capacityConfig);\n\n        _grantRole(DEFAULT_ADMIN_ROLE, params.admin);\n        _grantRole(ADMIN_ROLE, params.adminRole);\n        _grantRole(CURATOR_ROLE, params.curatorRole);\n        _grantRole(ALLOCATOR_ROLE, params.allocatorRole);\n        _grantRole(CONFIG_ADMIN_ROLE, params.configAdminRole);\n    }\n\n    // =========================================================================\n    // createCoverOrder\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function createCoverOrder(\n        address buyer,\n        address payoutRecipient,\n        string calldata beneficiaryAddress,\n        address premiumToken,\n        MarketAllocationInput[] calldata markets,\n        CoverOrderType orderType\n    ) external onlyRole(CURATOR_ROLE) returns (uint256 coverOrderId) {\n        _requireNonZero(buyer);\n        _requireNonZero(payoutRecipient);\n        if (bytes(beneficiaryAddress).length == 0) revert InvalidZeroAddress();\n        if (markets.length == 0) revert InvalidMarketsLength();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        if (!$.supportedPremiumTokens.contains(premiumToken)) revert UnsupportedPremiumToken();\n\n        uint256 targetPeriod = _currentPeriod() + 1;\n        uint256 periodDuration = uint256(_periodDuration(targetPeriod));\n        if (periodDuration == 0) revert InvalidPeriodDuration();\n\n        coverOrderId = $.nextCoverOrderId++;\n\n        (uint256 totalCoverAmount, uint256 totalPremiumAmount, uint256 sumWeightedRate) = _processMarketAllocations(\n            coverOrderId,\n            markets,\n            periodDuration,\n            targetPeriod\n        );\n\n        uint256 weightedAvgRate = sumWeightedRate / totalCoverAmount;\n\n        CoverOrder storage order = $.orders[coverOrderId];\n        order.buyer = buyer;\n        order.payoutRecipient = payoutRecipient;\n        order.beneficiaryAddress = beneficiaryAddress;\n        order.premiumToken = premiumToken;\n        order.totalCoverAmount = totalCoverAmount;\n        order.totalPremiumAmount = totalPremiumAmount;\n        order.weightedAvgRate = weightedAvgRate;\n        order.orderType = orderType;\n        order.status = CoverOrderStatus.PENDING;\n        order.period = targetPeriod;\n\n        $.ordersIdByPeriod[targetPeriod].push(coverOrderId);\n\n        emit CoverOrderCreated(\n            coverOrderId,\n            buyer,\n            payoutRecipient,\n            beneficiaryAddress,\n            premiumToken,\n            totalCoverAmount,\n            totalPremiumAmount,\n            weightedAvgRate,\n            orderType,\n            targetPeriod\n        );\n    }\n\n    /// @dev Validates each market allocation, persists it under `coverOrderId`,\n    ///      and returns aggregate totals. Extracted from `createCoverOrder` to\n    ///      keep stack pressure low under viaIR\n    function _processMarketAllocations(\n        uint256 coverOrderId,\n        MarketAllocationInput[] calldata markets,\n        uint256 periodDuration,\n        uint256 targetPeriod\n    ) private returns (uint256, uint256, uint256) {\n        uint256 totalCoverAmount;\n        uint256 totalPremiumAmount;\n        uint256 sumWeightedRate;\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        uint256 minMarketCover = _getEffectiveCapacityConfig(targetPeriod).minOrderMarketCoverAmount;\n\n        for (uint256 i; i < markets.length; ++i) {\n            MarketAllocationInput calldata ma = markets[i];\n            _validateMarketAllocation(ma, markets, i, minMarketCover, targetPeriod);\n\n            totalCoverAmount += ma.coverAmount;\n            sumWeightedRate += uint256(ma.coverRateAnnual) * ma.coverAmount;\n\n            totalPremiumAmount += _calculatePremium(ma.coverAmount, ma.coverRateAnnual, periodDuration);\n\n            MarketAllocation storage stored = $.orderMarkets[coverOrderId].push();\n            stored.marketId = ma.marketId;\n            stored.coverRateAnnual = ma.coverRateAnnual;\n            stored.coverAmount = ma.coverAmount;\n            // allocatedCoverAmount stays 0 (set on settle).\n        }\n\n        return (totalCoverAmount, totalPremiumAmount, sumWeightedRate);\n    }\n\n    function _calculatePremium(\n        uint256 coverAmount,\n        uint32 coverRateAnnual,\n        uint256 periodDuration\n    ) private pure returns (uint256) {\n        return\n            coverAmount.mulDiv(\n                uint256(coverRateAnnual) * periodDuration,\n                BPS_DENOMINATOR * SECONDS_PER_YEAR,\n                Math.Rounding.Ceil\n            );\n    }\n\n    /// @dev Validates a single market allocation (zero-values, min cover, duplicates,\n    ///      market exists & enabled at targetPeriod). Extracted to reduce stack pressure.\n    function _validateMarketAllocation(\n        MarketAllocationInput calldata ma,\n        MarketAllocationInput[] calldata markets,\n        uint256 i,\n        uint256 minMarketCover,\n        uint256 targetPeriod\n    ) private view {\n        if (ma.coverAmount == 0 || ma.coverRateAnnual == 0) revert InvalidMarketsZeroValue();\n        if (ma.coverAmount < minMarketCover) revert OrderMarketCoverAmountTooLow(ma.coverAmount, minMarketCover);\n\n        // Duplicate market check via O(n²) backwards scan\n        for (uint256 j; j < i; ++j) {\n            if (markets[j].marketId == ma.marketId) revert DuplicateMarket();\n        }\n\n        Market storage m = _getStorage().supportedMarkets[ma.marketId];\n        if (m.chainId == 0) revert MarketNotFound();\n        if (_getEffectiveProtocolConcentration(_getProtocolConcentrationHash(m.chainId, m.protocol), targetPeriod) == 0)\n            revert ZeroProtocolConcentrationForMarket();\n    }\n\n    // =========================================================================\n    // commitAllocation — Merkle commit\n    // =========================================================================\n\n    /**\n     * @inheritdoc ICoverOrderAllocator\n     * @dev The vault asset price in USD is fetched from the registered `priceFeedAdapter`\n     *      oracle, validated against `maxPriceAge` inside `PriceFeed.getPrice`. Capacity is\n     *      recomputed live and widened by the period's `divergenceToleranceBps` to bound\n     *      the caller's `matchingCapacity`.\n     */\n    function commitAllocation(\n        uint256 commitmentPeriod,\n        bytes32 merkleRoot,\n        uint256 totalAllocated,\n        uint256 matchingCapacity\n    ) external onlyRole(ALLOCATOR_ROLE) {\n        if (merkleRoot == bytes32(0)) revert InvalidMerkleRoot();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        uint256 currentPeriod = _currentPeriod();\n        if (commitmentPeriod != currentPeriod) revert InvalidCommitmentPeriod(commitmentPeriod, currentPeriod);\n        if ($.allocationCommitments[currentPeriod].root != bytes32(0)) revert PeriodAlreadyCommitted();\n        uint48 graceExpiresAt = uint48(block.timestamp) + $.settlementGracePeriod;\n        if (graceExpiresAt >= $.vault.currentPeriodEnd()) revert CommitTooCloseToPeriodEnd();\n\n        _validateMatchingCapacity($, currentPeriod, matchingCapacity, totalAllocated);\n\n        AllocationCommitment storage commit = $.allocationCommitments[currentPeriod];\n        commit.root = merkleRoot;\n        commit.totalAvailableCapacity = matchingCapacity;\n        commit.totalDeclaredAllocated = totalAllocated;\n        commit.graceExpiresAt = graceExpiresAt;\n\n        emit AllocationCommitted(currentPeriod, merkleRoot, matchingCapacity, totalAllocated);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function recommitAllocation(\n        uint256 period,\n        bytes32 newMerkleRoot,\n        uint256 newTotalAllocated,\n        uint256 newMatchingCapacity\n    ) external onlyRole(CONFIG_ADMIN_ROLE) {\n        if (newMerkleRoot == bytes32(0)) revert InvalidMerkleRoot();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        AllocationCommitment storage commit = _replaceableCommitment($, period);\n\n        uint48 graceExpiresAt = uint48(block.timestamp) + $.settlementGracePeriod;\n        if (graceExpiresAt >= $.vault.currentPeriodEnd()) revert CommitTooCloseToPeriodEnd();\n\n        // Validate against fresh capacity (symmetric with commitAllocation) so recommit can\n        // capture recovered price/FLB and stays bound to the period's real collateral within\n        // tolerance.\n        _validateMatchingCapacity($, period, newMatchingCapacity, newTotalAllocated);\n\n        commit.root = newMerkleRoot;\n        commit.totalAvailableCapacity = newMatchingCapacity;\n        commit.totalDeclaredAllocated = newTotalAllocated;\n        commit.graceExpiresAt = graceExpiresAt;\n\n        emit AllocationCommitted(period, newMerkleRoot, newMatchingCapacity, newTotalAllocated);\n    }\n\n    /**\n     * @dev A commitment stores the capacity THE MATCHER RAN AGAINST (`matchingCapacity`),\n     *      not a capacity recomputed at transaction time: settlement re-derives the merkle\n     *      tree off-chain from the commitment, so the stored value must be the exact input\n     *      that produced the committed root.\n     */\n    function _validateMatchingCapacity(\n        CoverOrderAllocatorStorage storage $,\n        uint256 period,\n        uint256 matchingCapacity,\n        uint256 totalAllocated\n    ) private view {\n        uint256 maxCapacity = _computeAvailableCapacity($, period);\n        if (matchingCapacity > maxCapacity) revert MatchingCapacityOverflow(matchingCapacity, maxCapacity);\n        if (totalAllocated > matchingCapacity) revert TotalAllocationOverflow(totalAllocated, matchingCapacity);\n    }\n\n    /**\n     * @inheritdoc ICoverOrderAllocator\n     * @dev Intentionally avoids `_computeAvailableCapacity` (and therefore the price feed):\n     *      withdrawing a bad root must remain possible while the oracle is down or stale,\n     *      which is exactly when `recommitAllocation` reverts.\n     */\n    function cancelCommitAllocation(uint256 period) external onlyRole(CONFIG_ADMIN_ROLE) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        bytes32 root = _replaceableCommitment($, period).root;\n\n        delete $.allocationCommitments[period];\n\n        emit AllocationCommitmentCancelled(period, root);\n    }\n\n    /// @dev Loads a period's commitment for replacement or cancellation, enforcing the shared\n    ///      guards: `period` must be the current vault period (live capacity and period-start\n    ///      reads only correspond to it), a commit must exist, and no order may have settled\n    ///      against it yet.\n    function _replaceableCommitment(\n        CoverOrderAllocatorStorage storage $,\n        uint256 period\n    ) private view returns (AllocationCommitment storage commit) {\n        uint256 currentPeriod = _currentPeriod();\n        if (period != currentPeriod) revert InvalidCommitmentPeriod(period, currentPeriod);\n\n        commit = $.allocationCommitments[period];\n        if (commit.root == bytes32(0)) revert NoCommitForPeriod();\n        if (commit.totalSettledCover > 0) revert SettlementsAlreadyStarted();\n    }\n\n    // =========================================================================\n    // settleCoverOrder / batchSettleCoverOrder\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function settleCoverOrder(\n        uint256 orderId,\n        MarketCoverAllocation[] calldata marketCoverAllocations,\n        bytes32[] calldata proof\n    ) external nonReentrant onlyRole(ALLOCATOR_ROLE) {\n        _settleCoverOrder(orderId, marketCoverAllocations, proof);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function batchSettleCoverOrder(SettleParams[] calldata params) external nonReentrant onlyRole(ALLOCATOR_ROLE) {\n        for (uint256 i; i < params.length; ++i) {\n            _settleCoverOrder(params[i].orderId, params[i].marketCoverAllocations, params[i].proof);\n        }\n    }\n\n    function _settleCoverOrder(\n        uint256 orderId,\n        MarketCoverAllocation[] calldata marketCoverAllocations,\n        bytes32[] calldata proof\n    ) internal {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        CoverOrder storage order = $.orders[orderId];\n        if (order.buyer == address(0)) revert InvalidOrder();\n        if (order.status != CoverOrderStatus.PENDING) revert OrderNotPending();\n        if (_currentPeriod() != order.period) revert SettleWindowExpired();\n\n        MarketAllocation[] storage markets = $.orderMarkets[orderId];\n        if (marketCoverAllocations.length != markets.length) revert InvalidAllocationMarketsLength();\n\n        AllocationCommitment storage commit = $.allocationCommitments[order.period];\n        if (commit.root == bytes32(0)) revert NoCommitForPeriod();\n\n        if (block.timestamp < commit.graceExpiresAt) revert GracePeriodActive(commit.graceExpiresAt);\n\n        // Verify merkle proof (double-hash leaf per OZ standard)\n        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(orderId, marketCoverAllocations))));\n        if (!MerkleProof.verify(proof, commit.root, leaf)) revert InvalidProof();\n\n        // Sum allocated cover, recompute the premium pro-rata per market (same formula\n        // and rounding as order creation), and enforce per-market concentration caps.\n        // The duration read here matches the one used at creation: a committed period's\n        // configuration is immutable (vault updates only apply from future periods).\n        uint256 periodDuration = uint256(_periodDuration(order.period));\n        uint256 allocatedCover;\n        uint256 allocatedPremium;\n        for (uint256 i; i < markets.length; ++i) {\n            if (marketCoverAllocations[i].marketId != markets[i].marketId) revert MarketIdMismatch();\n\n            uint256 mCover = marketCoverAllocations[i].allocatedCover;\n            if (mCover > markets[i].coverAmount) revert MarketAllocationOverflow(mCover, markets[i].coverAmount);\n\n            allocatedCover += mCover;\n            allocatedPremium += _calculatePremium(mCover, markets[i].coverRateAnnual, periodDuration);\n\n            // Set settled amount\n            markets[i].allocatedCoverAmount = mCover;\n\n            // Per-protocolConcentration cap: protocolConcentrationBps * totalAvailableCapacity / BPS\n            // The cap comes from the checkpoint active at order.period.\n            Market storage mStored = $.supportedMarkets[marketCoverAllocations[i].marketId];\n            bytes32 concHash = _getProtocolConcentrationHash(mStored.chainId, mStored.protocol);\n            uint256 newProtocolConcentrationCover =\n                $.protocolConcentrationSettledCover[order.period][concHash] + mCover;\n            uint256 protocolConcentrationCap =\n                (_getEffectiveProtocolConcentration(concHash, order.period) * commit.totalAvailableCapacity) /\n                    BPS_DENOMINATOR;\n            if (newProtocolConcentrationCover > protocolConcentrationCap)\n                revert ProtocolConcentrationOverflow(newProtocolConcentrationCover, protocolConcentrationCap);\n\n            $.protocolConcentrationSettledCover[order.period][concHash] = newProtocolConcentrationCover;\n        }\n\n        if (allocatedCover == 0) revert ZeroAllocation();\n\n        // A full match allocates every market exactly, so the recomputed premium equals\n        // `totalPremiumAmount` by construction (same per-market formula and rounding).\n        order.status = allocatedCover == order.totalCoverAmount ? CoverOrderStatus.MATCHED : CoverOrderStatus.PARTIAL;\n\n        order.allocatedCoverAmount = allocatedCover;\n        order.allocatedPremiumAmount = allocatedPremium;\n\n        commit.totalSettledCover += allocatedCover;\n        if (commit.totalSettledCover > commit.totalDeclaredAllocated)\n            revert TotalSettledOverflow(commit.totalSettledCover, commit.totalDeclaredAllocated);\n        commit.totalSettledPremium += allocatedPremium;\n\n        uint256 finalPremiumNative = Decimals.convert(\n            allocatedPremium,\n            CANONICAL_DECIMALS,\n            $.premiumTokenDecimals[order.premiumToken],\n            Math.Rounding.Ceil\n        );\n        IERC20(order.premiumToken).safeTransferFrom(order.buyer, $.premiumCollector, finalPremiumNative);\n\n        $.coverNFT.safeMint(order.buyer, orderId);\n\n        emit CoverOrderSettled(orderId, order.status, allocatedCover, allocatedPremium);\n    }\n\n    // =========================================================================\n    // cancelCoverOrder\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function cancelCoverOrder(uint256 coverOrderId) external onlyRole(CURATOR_ROLE) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        CoverOrder storage order = $.orders[coverOrderId];\n        if (order.buyer == address(0)) revert InvalidOrder();\n        if (order.status != CoverOrderStatus.PENDING) revert OrderNotPending();\n\n        order.status = CoverOrderStatus.CANCELLED;\n\n        emit CoverOrderCancelled(coverOrderId);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function cancelExpiredOrders(uint256[] calldata coverOrderIds) external {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        uint256 currentPeriod = _currentPeriod();\n        for (uint256 i; i < coverOrderIds.length; ++i) {\n            uint256 coverOrderId = coverOrderIds[i];\n            CoverOrder storage order = $.orders[coverOrderId];\n            if (order.buyer == address(0)) revert InvalidOrder();\n            if (order.status != CoverOrderStatus.PENDING) revert OrderNotPending();\n            if (order.period >= currentPeriod) revert OrderNotExpired();\n\n            order.status = CoverOrderStatus.CANCELLED;\n\n            emit CoverOrderCancelled(coverOrderId);\n        }\n    }\n\n    // =========================================================================\n    // setPremiumCollector\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function setPremiumCollector(address newCollector) external onlyRole(ADMIN_ROLE) {\n        _setPremiumCollector(newCollector);\n    }\n\n    function _setPremiumCollector(address newCollector) internal {\n        _requireNonZero(newCollector);\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        address old = $.premiumCollector;\n        $.premiumCollector = newCollector;\n\n        emit PremiumCollectorUpdated(old, newCollector);\n    }\n\n    // =========================================================================\n    // Oracle (vault asset USD price feed) management\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function setPriceFeedAdapter(IAggregatorV3 newPriceFeedAdapter) external onlyRole(ADMIN_ROLE) {\n        _setPriceFeedAdapter(newPriceFeedAdapter);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function setMaxPriceAge(uint48 newMaxPriceAge) external onlyRole(ADMIN_ROLE) {\n        _setMaxPriceAge(newMaxPriceAge);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function setSettlementGracePeriod(uint48 newGracePeriod) external onlyRole(CONFIG_ADMIN_ROLE) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        if (newGracePeriod > MAX_GRACE_PERIOD) revert InvalidGracePeriod(newGracePeriod, MAX_GRACE_PERIOD);\n\n        uint48 oldGracePeriod = $.settlementGracePeriod;\n        $.settlementGracePeriod = newGracePeriod;\n        emit SettlementGracePeriodUpdated(oldGracePeriod, newGracePeriod);\n    }\n\n    function _setPriceFeedAdapter(IAggregatorV3 newPriceFeedAdapter) internal {\n        _requireNonZero(address(newPriceFeedAdapter));\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n\n        uint8 newPriceFeedDecimals = newPriceFeedAdapter.decimals();\n        if (newPriceFeedDecimals < 6 || newPriceFeedDecimals > 18) {\n            revert InvalidPriceFeedDecimals(newPriceFeedDecimals);\n        }\n\n        address oldPriceFeedAdapter = address($.priceFeedAdapter);\n        uint8 oldPriceFeedDecimals = $.priceFeedDecimals;\n\n        $.priceFeedAdapter = newPriceFeedAdapter;\n        $.priceFeedDecimals = newPriceFeedDecimals;\n\n        emit PriceFeedUpdated(\n            oldPriceFeedAdapter,\n            oldPriceFeedDecimals,\n            address(newPriceFeedAdapter),\n            newPriceFeedDecimals\n        );\n    }\n\n    function _setMaxPriceAge(uint48 newMaxPriceAge) internal {\n        if (newMaxPriceAge == 0) revert InvalidMaxPriceAge();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        uint48 oldMaxPriceAge = $.maxPriceAge;\n        $.maxPriceAge = newMaxPriceAge;\n\n        emit MaxPriceAgeUpdated(oldMaxPriceAge, newMaxPriceAge);\n    }\n\n    // =========================================================================\n    // setCapacityConfig\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function setCapacityConfig(CapacityConfig calldata config) external onlyRole(CONFIG_ADMIN_ROLE) {\n        _setCapacityConfig(config);\n    }\n\n    function _setCapacityConfig(CapacityConfig calldata config) internal {\n        if (config.minCAR < MIN_CAR_BPS || config.minCAR > MAX_CAR_BPS) revert InvalidMinCAR();\n        _requireNonZero(address(config.firstLossBufferToken));\n        _requireNonZero(config.firstLossBuffer);\n        if (config.effectiveLeverage == 0 || config.effectiveLeverage > MAX_LEVERAGE_FACTOR * config.minCAR)\n            revert InvalidLeverage();\n        if (config.minOrderMarketCoverAmount == 0) revert InvalidMinOrderMarketCoverAmount();\n        if (config.divergenceToleranceBps > MAX_DIVERGENCE_TOLERANCE_BPS)\n            revert InvalidDivergenceTolerance(config.divergenceToleranceBps);\n        _readDecimals(address(config.firstLossBufferToken));\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        uint256 idx = $.capacityConfigHistory.length;\n        $.capacityConfigHistory.push(config);\n        // First-ever config is effective from period 0 so any past-period\n        // lookup hits a real checkpoint. Subsequent updates take effect next period.\n        uint32 effectivePeriod = idx == 0 ? 0 : uint32(_currentPeriod() + 1);\n        $.capacityConfigCheckpoints.push(effectivePeriod, uint224(idx));\n\n        emit CapacityConfigUpdated(config);\n    }\n\n    function _getEffectiveCapacityConfig(uint256 period) internal view returns (CapacityConfig storage) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        uint224 idx = $.capacityConfigCheckpoints.upperLookupRecent(uint32(period));\n        return $.capacityConfigHistory[uint256(idx)];\n    }\n\n    /// @notice Recomputes the period's effective cover capacity from live inputs.\n    /// @dev Values staked assets as of the current period start (read strictly before the\n    ///      boundary second), so it is only meaningful for the current period (enforced by\n    ///      callers). Capacity is in canonical USD.\n    ///      The divergence tolerance is folded in here as the period's EFFECTIVE capacity, so\n    ///      both the global allocation cap (commit/recommit) and the per-protocol concentration\n    ///      caps in `_settleCoverOrder` (which read `commit.totalAvailableCapacity`) scale by the\n    ///      same margin — a tree committed within tolerance therefore stays settleable.\n    function _computeAvailableCapacity(\n        CoverOrderAllocatorStorage storage $,\n        uint256 period\n    ) internal view returns (uint256 totalAvailableCapacity) {\n        uint256 assetPriceUSD = $.priceFeedAdapter.getPrice($.maxPriceAge);\n\n        CapacityConfig storage config = _getEffectiveCapacityConfig(period);\n\n        uint256 firstLossBufferUSDCanonical = Decimals.convert(\n            config.firstLossBufferToken.balanceOf(config.firstLossBuffer),\n            _readDecimals(address(config.firstLossBufferToken)),\n            CANONICAL_DECIMALS,\n            Math.Rounding.Floor\n        );\n        // Use periodStart - 1 so the inclusive lookup selects timestamps < periodStart, not <= periodStart.\n        // This excludes withdrawals at the period start and uses the same cutoff as payout.\n        // The deploy epoch is > 0, so the subtraction cannot underflow.\n        uint48 periodStart = $.vault.currentPeriodStart();\n        uint256 totalAssetsCanonical = Decimals.convert(\n            $.vault.totalAssetsAt(periodStart - 1),\n            $.vaultAssetDecimals,\n            CANONICAL_DECIMALS,\n            Math.Rounding.Floor\n        );\n        uint256 stakedAssetsValueUSDCanonical = totalAssetsCanonical.mulDiv(assetPriceUSD, 10 ** $.priceFeedDecimals);\n        uint256 availableCollateralCanonical = firstLossBufferUSDCanonical + stakedAssetsValueUSDCanonical;\n\n        uint256 strictCapacity = availableCollateralCanonical.mulDiv(config.effectiveLeverage, config.minCAR);\n        // Fold in the divergence tolerance as the period's effective capacity.\n        totalAvailableCapacity = strictCapacity.mulDiv(\n            BPS_DENOMINATOR + config.divergenceToleranceBps,\n            BPS_DENOMINATOR\n        );\n    }\n\n    function _getEffectiveProtocolConcentration(\n        bytes32 protocolConcentrationHash,\n        uint256 period\n    ) internal view returns (uint256) {\n        return\n            uint256(\n                _getStorage().protocolConcentrationCheckpoints[protocolConcentrationHash].upperLookupRecent(\n                    uint32(period)\n                )\n            );\n    }\n\n    function _getProtocolConcentrationHash(uint64 chainId, string memory protocol) internal pure returns (bytes32) {\n        return keccak256(abi.encode(chainId, protocol));\n    }\n\n    /// @dev Shared write path for setProtocolConcentration and initialize. Always pushes the\n    ///      checkpoint at currentPeriod() + 1. Validates bps, registers the hash on first\n    ///      sight, emits ProtocolConcentrationUpdated. Per-protocolConcentration bps act as independent\n    ///      ceilings: no aggregate sum invariant is enforced — the global cover bound is\n    ///      enforced via `commit.totalAvailableCapacity` / `TotalAllocationOverflow` in\n    ///      `commitAllocation`.\n    function _setProtocolConcentration(ProtocolConcentrationInput calldata c) internal {\n        if (c.chainId == 0) revert InvalidChainId();\n        if (bytes(c.protocol).length == 0) revert InvalidProtocolConcentration();\n        if (c.maxProtocolConcentrationBps > BPS_DENOMINATOR) revert InvalidProtocolConcentration();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        bytes32 hash = _getProtocolConcentrationHash(c.chainId, c.protocol);\n\n        uint256 oldShare = $.protocolConcentrationCheckpoints[hash].latest();\n\n        ProtocolConcentration storage id = $.protocolConcentrations[hash];\n        if (id.chainId == 0) {\n            id.protocol = c.protocol;\n            id.chainId = c.chainId;\n            $.supportedProtocolConcentrationHashes.push(hash);\n            emit ProtocolConcentrationRegistered(hash, c.protocol, c.chainId);\n        }\n        uint32 effectivePeriod = uint32(_currentPeriod() + 1);\n        $.protocolConcentrationCheckpoints[hash].push(effectivePeriod, uint224(c.maxProtocolConcentrationBps));\n\n        emit ProtocolConcentrationUpdated(hash, oldShare, c.maxProtocolConcentrationBps);\n    }\n\n    // =========================================================================\n    // SupportedMarkets functions\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function addSupportedMarket(Market calldata newMarket) external onlyRole(CONFIG_ADMIN_ROLE) returns (bytes32) {\n        return _addSupportedMarket(newMarket);\n    }\n\n    function _addSupportedMarket(Market memory newMarket) internal returns (bytes32 marketId) {\n        if (newMarket.chainId == 0) revert InvalidChainId();\n\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        marketId = _getMarketId(newMarket.chainId, newMarket.protocol, newMarket.market);\n\n        Market storage m = $.supportedMarkets[marketId];\n        if (m.chainId != 0) revert MarketAlreadyExists();\n\n        // Add market to storage\n        m.chainId = newMarket.chainId;\n        m.protocol = newMarket.protocol;\n        m.market = newMarket.market;\n\n        $.supportedMarketIds.push(marketId);\n\n        emit MarketAdded(marketId, newMarket.chainId, newMarket.protocol, newMarket.market);\n    }\n\n    function _getMarketId(uint64 chainId, string memory protocol, bytes32 market) internal pure returns (bytes32) {\n        return keccak256(abi.encode(chainId, protocol, market));\n    }\n\n    /**\n     * @inheritdoc ICoverOrderAllocator\n     * @dev The new cap becomes effective at currentPeriod() + 1 — the same period in which\n     *      orders created RIGHT NOW will settle. **Lowering a cap mid-period can therefore\n     *      leave already-created orders unsettleable**: the order was created with the assumption\n     *      that the cap was X, but `_settleCoverOrder` will read the new lower cap and may revert\n     *      `ProtocolConcentrationOverflow`.\n     *\n     *      Curator MUST coordinate with the off-chain matching engine to avoid this:\n     *        - Raising a cap mid-period is always safe.\n     *        - Lowering a cap is only safe if no orders pointing to this protocolConcentration exist\n     *          in the same period, or if the curator excludes the affected orders from the\n     *          matching tree (they will remain PENDING and can be cancelled).\n     *\n     *      A future hard mitigation would be to defer decreases to currentPeriod() + 2,\n     *      preserving the original cap for orders already on the book; not implemented today\n     *      so that the curator retains immediate control.\n     */\n    function setProtocolConcentration(\n        ProtocolConcentrationInput calldata protocolConcentration\n    ) external onlyRole(CONFIG_ADMIN_ROLE) {\n        _setProtocolConcentration(protocolConcentration);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function batchSetProtocolConcentration(\n        ProtocolConcentrationInput[] calldata protocolConcentrations\n    ) external onlyRole(CONFIG_ADMIN_ROLE) {\n        for (uint256 i; i < protocolConcentrations.length; ++i) {\n            _setProtocolConcentration(protocolConcentrations[i]);\n        }\n    }\n\n    // =========================================================================\n    // Premium token management\n    // =========================================================================\n\n    /// @inheritdoc ICoverOrderAllocator\n    function addSupportedPremiumToken(address token) external onlyRole(CONFIG_ADMIN_ROLE) {\n        _addSupportedPremiumToken(token);\n    }\n\n    function _addSupportedPremiumToken(address token) internal {\n        _requireNonZero(token);\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        if (!$.supportedPremiumTokens.add(token)) revert PremiumTokenAlreadySupported();\n\n        $.premiumTokenDecimals[token] = _readDecimals(token);\n\n        emit PremiumTokenAdded(token);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function removeSupportedPremiumToken(address token) external onlyRole(CONFIG_ADMIN_ROLE) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        if (!$.supportedPremiumTokens.remove(token)) revert UnsupportedPremiumToken();\n\n        emit PremiumTokenRemoved(token);\n    }\n\n    // =========================================================================\n    // View functions\n    // =========================================================================\n\n    function isPremiumTokenSupported(address token) external view returns (bool) {\n        return _getStorage().supportedPremiumTokens.contains(token);\n    }\n\n    /// @inheritdoc ICoverOrderAllocator\n    function getSupportedPremiumTokens() external view returns (address[] memory) {\n        return _getStorage().supportedPremiumTokens.values();\n    }\n\n    function vault() external view returns (IFirelightVault) {\n        return _getStorage().vault;\n    }\n\n    function coverNFT() external view returns (CoverNFT) {\n        return _getStorage().coverNFT;\n    }\n\n    function priceFeedAdapter() external view returns (IAggregatorV3) {\n        return _getStorage().priceFeedAdapter;\n    }\n\n    function maxPriceAge() external view returns (uint48) {\n        return _getStorage().maxPriceAge;\n    }\n\n    function settlementGracePeriod() external view returns (uint48) {\n        return _getStorage().settlementGracePeriod;\n    }\n\n    function priceFeedDecimals() external view returns (uint8) {\n        return _getStorage().priceFeedDecimals;\n    }\n\n    function premiumCollector() external view returns (address) {\n        return _getStorage().premiumCollector;\n    }\n\n    function nextCoverOrderId() external view returns (uint256) {\n        return _getStorage().nextCoverOrderId;\n    }\n\n    function getCoverOrder(uint256 coverOrderId) external view returns (CoverOrder memory) {\n        return _getStorage().orders[coverOrderId];\n    }\n\n    function getCoverOrderMarkets(uint256 coverOrderId) external view returns (MarketAllocation[] memory) {\n        return _getStorage().orderMarkets[coverOrderId];\n    }\n\n    function getCoverOrderMarketInfo(\n        uint256 coverOrderId,\n        bytes32 marketId\n    ) external view returns (uint256 period, uint256 allocatedCoverAmount, address payoutRecipient) {\n        CoverOrderAllocatorStorage storage $ = _getStorage();\n        MarketAllocation[] storage markets = $.orderMarkets[coverOrderId];\n        uint256 len = markets.length;\n        for (uint256 i; i < len; ) {\n            if (markets[i].marketId == marketId) {\n                CoverOrder storage order = $.orders[coverOrderId];\n                return (order.period, markets[i].allocatedCoverAmount, order.payoutRecipient);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function getSupportedMarket(bytes32 marketId) external view returns (Market memory) {\n        return _getStorage().supportedMarkets[marketId];\n    }\n\n    function getEffectiveCapacityConfig() external view returns (CapacityConfig memory) {\n        return _getEffectiveCapacityConfig(_currentPeriod() + 1);\n    }\n\n    function getCapacityConfigAt(uint256 period) external view returns (CapacityConfig memory) {\n        return _getEffectiveCapacityConfig(period);\n    }\n\n    function getCoverOrdersIdByPeriod(uint256 period) external view returns (uint256[] memory) {\n        return _getStorage().ordersIdByPeriod[period];\n    }\n\n    function getAllocationCommitment(uint256 period) external view returns (AllocationCommitment memory) {\n        return _getStorage().allocationCommitments[period];\n    }\n\n    function getSupportedMarketIds() external view returns (bytes32[] memory) {\n        return _getStorage().supportedMarketIds;\n    }\n\n    function getSupportedProtocolConcentrationHashes() external view returns (bytes32[] memory) {\n        return _getStorage().supportedProtocolConcentrationHashes;\n    }\n\n    function getProtocolConcentrationFromHash(\n        bytes32 protocolConcentrationHash\n    ) external view returns (ProtocolConcentration memory) {\n        return _getStorage().protocolConcentrations[protocolConcentrationHash];\n    }\n\n    function getProtocolConcentrationSettledCover(\n        uint256 period,\n        bytes32 protocolConcentrationHash\n    ) external view returns (uint256) {\n        return _getStorage().protocolConcentrationSettledCover[period][protocolConcentrationHash];\n    }\n\n    function getEffectiveProtocolConcentration(bytes32 protocolConcentrationHash) external view returns (uint256) {\n        return _getEffectiveProtocolConcentration(protocolConcentrationHash, _currentPeriod() + 1);\n    }\n\n    function getProtocolConcentrationAt(\n        bytes32 protocolConcentrationHash,\n        uint256 period\n    ) external view returns (uint256) {\n        return _getEffectiveProtocolConcentration(protocolConcentrationHash, period);\n    }\n\n    // =========================================================================\n    // Decimals helpers\n    // =========================================================================\n\n    /// @dev Reads ERC20.decimals() and reverts if > CANONICAL_DECIMALS (we only support ≤ canonical).\n    function _readDecimals(address token) private view returns (uint8 dec) {\n        dec = IERC20Metadata(token).decimals();\n        if (dec > CANONICAL_DECIMALS) revert UnsupportedDecimals(dec);\n    }\n\n    /// @dev Shared zero-address guard; deduplicated into a helper to keep bytecode size down.\n    function _requireNonZero(address account) private pure {\n        if (account == address(0)) revert InvalidZeroAddress();\n    }\n\n    /// @dev Duration (seconds) of `period` per the vault's configuration.\n    function _periodDuration(uint256 period) private view returns (uint48) {\n        return _getStorage().vault.periodConfigurationAtNumber(period).duration;\n    }\n\n    /// @dev Current vault period; deduplicated into a helper to keep bytecode size down.\n    function _currentPeriod() private view returns (uint256) {\n        return _getStorage().vault.currentPeriod();\n    }\n}\n","deployed_bytecode":"0x6080604052600436101561001257600080fd5b60003560e01c806301ffc9a71461038757806304acf36814610382578063061831101461037d578063113e6e76146103785780631584410a146103735780631b0eeb7e1461036e5780631c5f5ceb146103695780631c87ad931461036457806322e359ad1461035f578063248a9ca31461035a57806325d8c1c514610355578063271de2ae146103505780632aa304d71461034b5780632f2ff15d1461034657806331a539b914610341578063325d62821461033c578063363768101461033757806336568abe1461033257806336807c631461032d57806336b50ff81461032857806342e53fcf146103235780634a2cfb541461031e5780634e37695a1461031957806352c9926014610314578063582670521461030f578063595fdd671461030a5780635d7b0cad14610305578063697209791461030057806375b238fc146102fb578063764e64cf146102f657806387a0611d146102f15780638b9c2cbf146102ec57806391d14854146102e757806392390479146102e257806392bbcf66146102dd5780639ae38bca146102d8578063a217fddf146102d3578063a25aa00b146102ce578063bc80feb3146102c9578063c0cb9233146102c4578063c78ef28c146102bf578063c7fb139b146102ba578063c81cbaa1146102b5578063cdb0cadb146102b0578063d3cc14ed146102ab578063d547741f146102a6578063db989a9f146102a1578063e33f823b1461029c578063e89ac07b14610297578063ea49248c14610292578063ef0595f51461028d578063f30554b514610288578063f779c85d14610283578063fbfa77cf1461027e5763fe1b61231461027957600080fd5b611d88565b611d52565b611d31565b611cfe565b611c2f565b611bbb565b611a71565b611a32565b611a05565b6119d1565b61191a565b6117f4565b6117cb565b611712565b6116e9565b611675565b611648565b611617565b6115fb565b6115ce565b611573565b61153d565b6114da565b611344565b6111ae565b611129565b611100565b611071565b61102b565b610f71565b610ef9565b610ece565b610e33565b610e0a565b610dd4565b610d95565b610d4b565b610d01565b610c6d565b610bb9565b610b8f565b610b28565b610afb565b610a43565b610962565b610944565b6108bf565b6107f1565b61071e565b6105a7565b610551565b610468565b61042e565b6103e2565b346103dd5760203660031901126103dd5760043563ffffffff60e01b81168091036103dd57602090637965db0b60e01b81149081156103cc575b506040519015158152f35b6301ffc9a760e01b149050386103c1565b600080fd5b346103dd5760203660031901126103dd576004356103fe612dfa565b906001820180921161041e5760209161041691612e67565b604051908152f35b611efd565b60009103126103dd57565b346103dd5760003660031901126103dd57600080516020615c208339815191525460405160089190911c6001600160a01b03168152602090f35b346103dd5760203660031901126103dd5761054d61049060043561048a612021565b50612f87565b60046040519161049f83611f54565b8054835260018101546001600160a01b038116602085015260a01c61ffff16604084015260028101546104e5906001600160a01b03166001600160a01b03166060850152565b60038101546080840152015460a08201526040519182918291909160a08060c083019480518452600180831b03602082015116602085015261ffff6040820151166040850152600180831b036060820151166060850152608081015160808501520151910152565b0390f35b346103dd5760003660031901126103dd57602065ffffffffffff600080516020615c208339815191525460a81c16604051908152f35b6001600160a01b038116036103dd57565b606435906105a582610587565b565b346103dd5760203660031901126103dd5760206105d76004356105c981610587565b6001600160a01b0316614dd5565b6040519015158152f35b634e487b7160e01b600052602160045260246000fd5b9060028210156106045752565b6105e1565b6004111561060457565b9061061d82610609565b52565b919082519283825260005b84811061064c575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161062b565b602080825282516001600160a01b031690820152610687602083015160408301906105f7565b61069960408301516060830190610613565b60608201516001600160a01b031660808201526101806101606106cb60808501518360a08601526101a0850190610620565b60a08501516001600160a01b031660c08501529360c081015160e085015260e081015161010085015261010081015161012085015261012081015161014085015261014081015182850152015191015290565b346103dd5760203660031901126103dd57600435600061016060405161074381611f74565b828152826020820152826040820152826060820152606060808201528260a08201528260c08201528260e0820152826101008201528261012082015282610140820152015260005260008051602061594083398151915260205261054d6107ad6040600020612227565b60405191829182610661565b602081526001600160401b038251166020820152606060406107e8602085015183838601526080850190610620565b93015191015290565b346103dd5760203660031901126103dd5760043560006040805161081481611f90565b8281526060602082015201526000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00660205261054d604060002060026040519161085e83611f90565b6001600160401b03815416835261087760018201612185565b602084015201546040820152604051918291826107b9565b9181601f840112156103dd578235916001600160401b0383116103dd576020808501948460051b0101116103dd57565b346103dd5760603660031901126103dd576004356024356001600160401b0381116103dd57366023820112156103dd578060040135906001600160401b0382116103dd573660248360061b830101116103dd57604435916001600160401b0383116103dd5761094293610938602494369060040161088f565b94909301906122e7565b005b346103dd5760203660031901126103dd576020610416600435612318565b346103dd5760203660031901126103dd5760043561097e612021565b50600052600080516020615b2083398151915260205261054d604060002065ffffffffffff6005604051926109b284611f54565b805484526001810154602085015260028101546040850152600381015460608501526004810154608085015201541660a08201526040519182918291909160a065ffffffffffff8160c08401958051855260208101516020860152604081015160408601526060810151606086015260808101516080860152015116910152565b65ffffffffffff8116036103dd57565b346103dd5760203660031901126103dd57600435610a6081610a33565b610a686130ca565b65ffffffffffff8116906170808211610ae057600080516020615b60833981519152805465ffffffffffff19811690931790556040805165ffffffffffff93841681529190921660208201527fc5a463d4ef3011e309d848d389bb7b7c23889c0611844319ea2c43c9543b2ac691819081015b0390a1005b50631f1c218960e01b60005260045261708060245260446000fd5b346103dd5760203660031901126103dd57610942600435610b1b81610587565b610b23613118565b61382b565b346103dd5760403660031901126103dd57610942602435600435610b4b82610587565b610b5c610b5782612318565b613202565b613c9d565b60206003198201126103dd576004356001600160401b0381116103dd57606090600401809203126103dd5790565b346103dd576020610416610bb4610ba536610b61565b610bad6130ca565b3690612390565b613f2c565b346103dd5760203660031901126103dd57600435610bd681610587565b610bde6130ca565b6001600160a01b0316610bf081615074565b15610c225760207f140755d6e5a015c6a602fd931764198cf5875820d73c092baf578bee102fd6ed91604051908152a1005b63216187cb60e21b60005260046000fd5b602060408183019282815284518094520192019060005b818110610c575750505090565b8251845260209384019390920191600101610c4a565b346103dd5760203660031901126103dd576004356000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00c602052604060002060405190816020825491828152019160005260206000209060005b818110610ceb5761054d85610cdf81870382611fe1565b60405191829182610c33565b8254845260209093019260019283019201610cc8565b346103dd5760403660031901126103dd57600435602435610d2181610587565b336001600160a01b03821603610d3a5761094291614057565b63334bd91960e11b60005260046000fd5b346103dd5760003660031901126103dd57602060405160128152f35b60206003198201126103dd57600435906001600160401b0382116103dd57610d919160040161088f565b9091565b346103dd57610da336610d67565b90610dac6130ca565b60005b828110610db857005b80610dce610dc9600193868661241b565b614160565b01610daf565b346103dd5760003660031901126103dd57600080516020615be0833981519152546040516001600160a01b039091168152602090f35b346103dd5760003660031901126103dd576020604051600080516020615ac08339815191528152f35b346103dd5760203660031901126103dd57600435610e4f6130ca565b7f102f71bf03a442e06446151ebf1aa14ee8a00abda0e6e23db350bdadb9c04a53610ec9610e7c83614334565b5483600052600080516020615b2083398151915260205260006005604082208281558260018201558260028201558260038201558260048201550155604051918291829190602083019252565b0390a2005b346103dd5760003660031901126103dd576020600080516020615ae083398151915254604051908152f35b346103dd5760003660031901126103dd57610f12612021565b50610f1b612dfa565b6001810180911161041e5761049061054d91612f87565b9181601f840112156103dd578235916001600160401b0383116103dd57602080850194606085020101116103dd57565b60a4359060028210156103dd57565b346103dd5760c03660031901126103dd57600435610f8e81610587565b602435610f9a81610587565b6044356001600160401b0381116103dd57366023820112156103dd578060040135926001600160401b0384116103dd5736602485840101116103dd57610fde610598565b92608435936001600160401b0385116103dd5761054d9561100661101b963690600401610f32565b9490936024611013610f62565b970191612476565b6040519081529081906020820190565b346103dd5761094261103c36610b61565b610dc96130ca565b6060602061106e938184526001600160401b03815116828501520151916040808201520190610620565b90565b346103dd5760203660031901126103dd576004356060602060405161109581611fab565b6000815201526000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd01160205261054d60406000206110ef6001604051926110dc84611fab565b6001600160401b03815416845201612185565b602082015260405191829182611044565b346103dd5760003660031901126103dd576020604051600080516020615ba08339815191528152f35b346103dd5760003660031901126103dd57611142612968565b60405180916020820160208352815180915260206040840192019060005b81811061116e575050500390f35b82516001600160a01b0316845285945060209384019390920191600101611160565b60809060031901126103dd5760043590602435906044359060643590565b346103dd576111bc36611190565b90916111c66130ca565b8015611333576111d584614334565b926112056111f7600080516020615b608339815191525465ffffffffffff1690565b65ffffffffffff42166128f0565b906004602061123761122b600080516020615a608339815191525460018060a01b031690565b6001600160a01b031690565b604051632c3ca22b60e11b815292839182905afa801561132e5765ffffffffffff916000916112ff575b501665ffffffffffff831610156112ee576112d1610ec99260057f9edc562117c283540e3b0753d6a0a669589c7897e1ba29a9aaefeb912c418b16976112a885898c614684565b868155876001820155846002820155019065ffffffffffff1665ffffffffffff19825416179055565b604051938493846040919493926060820195825260208201520152565b63ab6d660760e01b60005260046000fd5b611321915060203d602011611327575b6113198183611fe1565b81019061290e565b38611261565b503d61130f565b612923565b639dd854d360e01b60005260046000fd5b346103dd5760c03660031901126103dd57600061135f6130ca565b600435612ee0811080156114cf575b6114c05761138761138261122b6024612ae3565b61439a565b6113946113826064612ae3565b60843580159182156114ad575b505061149e5760a4351561148f576103e861ffff6113bf60446148f5565b1611611469576113da6113d561122b6024612ae3565b614d41565b5061140f600080516020615bc0833981519152546113f860046148ff565b806114475782905b6001600160e01b03169061542b565b50507f4d65ea4765c1c204c4a6882a91a420cb6f1d9fec39f5a6d40e5ebf591c2c0564604051806114416004826149f0565b0390a180f35b61146361145a611455612dfa565b611f13565b63ffffffff1690565b90611400565b61148c61147660446148f5565b6389cb95e960e01b835261ffff16600452602490565b90fd5b637f349ee160e11b8152600490fd5b633fe89cb960e11b8152600490fd5b6114b8919250613306565b1038806113a1565b63197f247760e01b8252600482fd5b5061c350811161136e565b346103dd5760403660031901126103dd57602060ff61153160243560043561150182610587565b600052600080516020615b40833981519152845260406000209060018060a01b0316600052602052604060002090565b54166040519015158152f35b346103dd5760003660031901126103dd57600080516020615900833981519152546040516001600160a01b039091168152602090f35b346103dd5760403660031901126103dd57600435602435906000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00d6020526040600020906000526020526020604060002054604051908152f35b346103dd5760203660031901126103dd576109426004356115ee81610587565b6115f6613118565b614bb1565b346103dd5760003660031901126103dd57602060405160008152f35b346103dd5760003660031901126103dd57602060ff600080516020615c208339815191525460d81c16604051908152f35b346103dd5760203660031901126103dd5761094260043561166881610587565b6116706130ca565b614c18565b346103dd5760003660031901126103dd57604051600080516020615a80833981519152548082526020820190600080516020615a8083398151915260005260206000209060005b8181106116d35761054d85610cdf81870382611fe1565b82548452602090930192600192830192016116bc565b346103dd5760003660031901126103dd576020604051600080516020615aa08339815191528152f35b346103dd5761172036610d67565b61172861308e565b611730613166565b60005b818110611751576109426001600080516020615b8083398151915255565b61175c81838561241b565b359061176981848661241b565b602081013590601e19813603018212156103dd57018035906001600160401b0382116103dd576020018160061b360381136103dd576001936117c5926117bd6117b386898b61241b565b60408101906129cd565b93909261334e565b01611733565b346103dd5760003660031901126103dd576020604051600080516020615a408339815191528152f35b346103dd5760203660031901126103dd576004356118106131b4565b600081815260008051602061594083398151915260205260409020805490916001600160a01b038216156118a75760ff8260a81c1661184e81610609565b6118965760ff60a81b19909116600360a81b179091556040519081527f091116832d5c5cf537cbf8f22b48e141643e4f959373984adaa4962cec96cb96908060208101610adb565b635d12a4a360e11b60005260046000fd5b63af61069360e01b60005260046000fd5b602060408183019282815284518094520192019060005b8181106118dc5750505090565b90919260206080600192606087518051835263ffffffff858201511685840152604081015160408401520151606082015201940191019190916118cf565b346103dd5760203660031901126103dd576004356000526000805160206159e08339815191526020526040600020805461195381612a02565b916119616040519384611fe1565b818352602083019060005260206000206000915b83831061198a576040518061054d87826118b8565b6004602060019260405161199d81611fc6565b8554815263ffffffff8587015416838201526002860154604082015260038601546060820152815201920192019190611975565b346103dd5760403660031901126103dd576109426024356004356119f482610587565b611a00610b5782612318565b614057565b346103dd5760203660031901126103dd57610942600435611a2581610a33565b611a2d613118565b614c98565b346103dd5760403660031901126103dd576060611a53602435600435612a35565b6040805193845260208401929092526001600160a01b031690820152f35b346103dd57611a7f36611190565b9091611a89613166565b801561133357611a97612dfa565b93848103611ba15750611aa984612052565b54611b9057611acf6111f7600080516020615b608339815191525465ffffffffffff1690565b600080516020615a6083398151915254600490602090611af7906001600160a01b031661122b565b604051632c3ca22b60e11b815292839182905afa801561132e5765ffffffffffff91600091611b71575b501665ffffffffffff821610156112ee57836112d1610ec992611b667f9edc562117c283540e3b0753d6a0a669589c7897e1ba29a9aaefeb912c418b1697878a614684565b60056112a889612052565b611b8a915060203d602011611327576113198183611fe1565b38611b21565b6383a1dec160e01b60005260046000fd5b631d56b54b60e31b600052600452602484905260445b6000fd5b346103dd5760003660031901126103dd5760405160008051602061598083398151915254808252602082019060008051602061598083398151915260005260206000209060005b818110611c195761054d85610cdf81870382611fe1565b8254845260209093019260019283019201611c02565b346103dd57611c3d36610d67565b90611c46612dfa565b9160005b818110611c5357005b611c5e818385612ad3565b3590611c698261206f565b8054909290611c806001600160a01b03821661122b565b156118a75760a81c60ff16611c9481610609565b611896578560098401541015611ced57825460ff60a81b1916600360a81b179092556001917f091116832d5c5cf537cbf8f22b48e141643e4f959373984adaa4962cec96cb9690611ce49061101b565b0390a101611c4a565b63796c85f360e01b60005260046000fd5b346103dd5760003660031901126103dd57602065ffffffffffff600080516020615b608339815191525416604051908152f35b346103dd5760403660031901126103dd576020610416602435600435612e67565b346103dd5760003660031901126103dd57600080516020615a60833981519152546040516001600160a01b039091168152602090f35b346103dd5760203660031901126103dd576004356001600160401b0381116103dd5761026060031982360301126103dd57600080516020615c0083398151915254906001600160401b03611df460ff604085901c1615611de7565b1590565b936001600160401b031690565b1680159081611ef5575b6001149081611eeb575b159081611ee2575b50611ed157611e599082611e4c60016001600160401b0319600080516020615c00833981519152541617600080516020615c0083398151915255565b611eac575b600401612b0c565b611e5f57005b600080516020615c00833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2908060208101610adb565b600080516020615c00833981519152805460ff60401b1916600160401b179055611e51565b63f92ee8a960e01b60005260046000fd5b90501538611e10565b303b159150611e08565b839150611dfe565b634e487b7160e01b600052601160045260246000fd5b906001820180921161041e57565b6127100190816127101161041e57565b9190820180921161041e57565b634e487b7160e01b600052604160045260246000fd5b60c081019081106001600160401b03821117611f6f57604052565b611f3e565b61018081019081106001600160401b03821117611f6f57604052565b606081019081106001600160401b03821117611f6f57604052565b604081019081106001600160401b03821117611f6f57604052565b608081019081106001600160401b03821117611f6f57604052565b90601f801991011681019081106001600160401b03821117611f6f57604052565b604051906105a561018083611fe1565b604051906105a5604083611fe1565b6040519061202e82611f54565b600060a0838281528260208201528260408201528260608201528260808201520152565b600052600080516020615b20833981519152602052604060002090565b600052600080516020615940833981519152602052604060002090565b6000526000805160206159e0833981519152602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd006602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00d602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00f602052604060002090565b60028210156106045752565b61061d82610609565b90600182811c9216801561217b575b602083101461216557565b634e487b7160e01b600052602260045260246000fd5b91607f169161215a565b90604051918260008254926121998461214b565b808452936001811690811561220557506001146121be575b506105a592500383611fe1565b90506000929192526020600020906000915b8183106121e95750509060206105a592820101386121b1565b60209193508060019154838589010152019101909184926121d0565b9050602092506105a594915060ff191682840152151560051b820101386121b1565b906009612232612002565b83546001600160a01b0381168252909390612271906122689061225f60a082901c60ff1660208901612136565b60a81c60ff1690565b60408601612142565b60018101546001600160a01b0316606085015261229060028201612185565b608085015260038101546001600160a01b031660a0850152600481015460c0850152600581015460e08501526006810154610100850152600781015461012085015260088101546101408501520154610160830152565b90612304949392916122f761308e565b6122ff613166565b61334e565b6001600080516020615b8083398151915255565b600052600080516020615b4083398151915260205260016040600020015490565b6001600160401b038116036103dd57565b9291926001600160401b038211611f6f5760405191612373601f8201601f191660200184611fe1565b8294818452818301116103dd578281602093846000960137010152565b9190916060818403126103dd57604051906123aa82611f90565b819381356123b781612339565b835260208201356001600160401b0381116103dd5782019181601f840112156103dd576123ee60409392836020869535910161234a565b60208501520135910152565b61106e903690612390565b634e487b7160e01b600052603260045260246000fd5b919081101561243d5760051b81013590605e19813603018212156103dd570190565b612405565b9161245c9183549060031b91821b91600019901b19161790565b9055565b634e487b7160e01b600052600060045260246000fd5b9396919596949290946124876131b4565b6124908561439a565b6124998661439a565b8115612661578715612650576124c2611de36124bd6001600160a01b03841661122b565b614dd5565b610c22576124d1611455612dfa565b936124e96124de866143aa565b65ffffffffffff1690565b801561263f578590600080516020615ae0833981519152549a61250b8c612672565b600080516020615ae083398151915255612525938c6144b2565b8261253291949294612697565b938661253d8c61206f565b80546001600160a01b0319166001600160a01b038b161781556001810180546001600160a01b0319166001600160a01b038d16179055612581838d600284016126f8565b6003810180546001600160a01b0319166001600160a01b0386161790558460048201558560058201558660068201556125ba88826127c2565b805460ff60a81b19168155600901558a6125fd886000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00c602052604060002090565b9061260791612822565b604051998a99612618998d8c61287c565b037f09ad29fb5a3daab22928c7284f1bbea8855c2ff7c3e3e5345576d9d840724eb191a190565b634f08daf360e11b60005260046000fd5b63a1d9979360e01b60005260046000fd5b63f6b2911f60e01b60005260046000fd5b600019811461041e5760010190565b634e487b7160e01b600052601260045260246000fd5b81156126a1570490565b612681565b601f82116126b357505050565b6000526020600020906020601f840160051c830193106126ee575b601f0160051c01905b8181106126e2575050565b600081556001016126d7565b90915081906126ce565b9092916001600160401b038111611f6f5761271d81612717845461214b565b846126a6565b6000601f821160011461275a57819061245c93949560009261274f575b50508160011b916000199060031b1c19161790565b01359050388061273a565b601f1982169461276f84600052602060002090565b91805b8781106127aa575083600195969710612790575b505050811b019055565b0135600019600384901b60f8161c19169055388080612786565b90926020600181928686013581550194019101612772565b90600281101561060457815460ff60a01b191660a09190911b60ff60a01b16179055565b906127f081610609565b815460ff60a81b191660a89190911b60ff60a81b16179055565b805482101561243d5760005260206000200190600090565b805490600160401b821015611f6f578161284491600161245c9401815561280a565b819391549060031b91821b91600019901b19161790565b908060209392818452848401376000828201840152601f01601f1916010190565b979390946128ec97936128c2936101209b979e9d9c989e8b5260018060a01b031660208b015260018060a01b031660408a015261014060608a015261014089019161285b565b6001600160a01b03909a16608087015260a086015260c085015260e08401526101008301906105f7565b0152565b9065ffffffffffff8091169116019065ffffffffffff821161041e57565b908160209103126103dd575161106e81610a33565b6040513d6000823e3d90fd5b6001600160a01b031660009081527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0126020526040902090565b60405190600080516020615b00833981519152548083528260208101600080516020615b0083398151915260005260206000209260005b8181106129b45750506105a592500383611fe1565b845483526001948501948794506020909301920161299f565b903590601e19813603018212156103dd57018035906001600160401b0382116103dd57602001918160051b360383136103dd57565b6001600160401b038111611f6f5760051b60200190565b805482101561243d5760005260206000209060021b0190600090565b600092600092600092806000526000805160206159e083398151915260205260406000209081549260005b848110612a6e575050505050565b81612a798286612a19565b505414612a8857600101612a60565b97505092935093505060005260008051602061594083398151915260205260016003612abe604060002095600987015495612a19565b5001549301549192916001600160a01b031690565b919081101561243d5760051b0190565b3561106e81610587565b908160209103126103dd575161106e81610587565b3561106e81610a33565b90612b1c61138261122b84612ae3565b6040820191612b3061138261122b85612ae3565b60c08101612b4061138282612ae3565b60e08201612b5061138282612ae3565b610100830191612b6261138284612ae3565b610120840191612b7461138284612ae3565b612c0b612bdc610140870198612b8c6113828b612ae3565b612b946151af565b612b9c614d31565b612bd7612ba889612ae3565b600080516020615a6083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612ae3565b600080516020615be083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60046020612c1b61122b88612ae3565b6040516338d52e0f60e01b815292839182905afa90811561132e57612c7691612c4c91600091612dbc575b50614d41565b60ff1660ff19600080516020615c20833981519152541617600080516020615c2083398151915255565b612c856115f660208701612ae3565b612c94611a2d60808701612b02565b612ca3610b2360608701612ae3565b60005b60a08601612cb481886129cd565b9050821015612ce05790612cda611670612bd783612cd46001968c6129cd565b90612ad3565b01612ca6565b5050919490929560005b6101608601612cf981886129cd565b9050821015612d225790612d1c610dc982612d166001958b6129cd565b9061241b565b01612cea565b5050919490929560005b6101808601612d3b81886129cd565b9050821015612d675790612d60610bb4612d5b83612d166001968c6129cd565b6123fa565b5001612d2c565b505090612d9f612daa612daf93612d9f612da5612db99a612d9f612d9a612d9f9a9b9e612bd76101a0612db49f01614a5b565b6139c1565b50612ae3565b613a61565b613af0565b613b7f565b613c0e565b50565b612dde915060203d602011612de4575b612dd68183611fe1565b810190612aed565b38612c46565b503d612dcc565b908160209103126103dd575190565b600080516020615a608339815191525460405162c080c360e31b815290602090829060049082906001600160a01b03165afa90811561132e57600091612e3e575090565b61106e915060203d602011612e60575b612e588183611fe1565b810190612deb565b503d612e4e565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00f60205263ffffffff604060002091169060009181549083829160058411612ee8575b612eb893508461533b565b80612ecc5750505b6001600160e01b031690565b612ed590614db9565b908252602082200190505460201c612ec0565b9192612ef3816151dd565b810390811161041e57612eb89385875263ffffffff82602089200154168410600014612f20575091612ead565b929150612f2c90611f13565b90612ead565b600080516020615bc08339815191525481101561243d57600080516020615bc08339815191526000526005602060002091020190600090565b805482101561243d576000526005602060002091020190600090565b63ffffffff1660006000805160206159a08339815191525481928160058111613011575b5090612fde93612fc9926000805160206159a083398151915261533b565b80612fe257505b6001600160e01b0316612f32565b5090565b906020612ff161300c93614db9565b916000805160206159a0833981519152815220015460201c90565b612fd0565b9361301b856151dd565b850394851161041e576000805160206159a083398151915284527f2060c037175d92fda9c6bae663cfb46d241cf6f66cac38481ca19c403ebfb792850154612fde95612fc994909163ffffffff1684101561307c5750915b91925093612fab565b92915061308890611f13565b90613073565b6002600080516020615b8083398151915254146130b9576002600080516020615b8083398151915255565b633ee5aeb560e01b60005260046000fd5b336000908152600080516020615c40833981519152602052604090205460ff16156130f157565b63e2517d3f60e01b60005233600452600080516020615aa083398151915260245260446000fd5b336000908152600080516020615a00833981519152602052604090205460ff161561313f57565b63e2517d3f60e01b60005233600452600080516020615ba083398151915260245260446000fd5b336000908152600080516020615a20833981519152602052604090205460ff161561318d57565b63e2517d3f60e01b60005233600452600080516020615a4083398151915260245260446000fd5b336000908152600080516020615960833981519152602052604090205460ff16156131db57565b63e2517d3f60e01b60005233600452600080516020615ac083398151915260245260446000fd5b6000818152600080516020615b408339815191526020908152604080832033845290915290205460ff16156132345750565b63e2517d3f60e01b6000523360045260245260446000fd5b90815260406020820181905281018390526060019160005b8181106132715750505090565b823584526020808401359085015260409384019390920191600101613264565b90604051916020830152602082526105a5604083611fe1565b9291906132b681612a02565b936132c46040519586611fe1565b602085838152019160051b81019283116103dd57905b8282106132e657505050565b81358152602091820191016132da565b919081101561243d5760061b0190565b908160050291600583040361041e57565b8181029291811591840414171561041e57565b9081526080810194939260609261334081610609565b602083015260408201520152565b9394919061335b8561206f565b80549096906001600160a01b038116156118a75760a81c60ff1661337e81610609565b6118965761338a612dfa565b9660098101978854809103613801576133a28861208c565b92835486036137f0576133b482612052565b9788549081156137df5760058a015465ffffffffffff164281116137c3575091611de391613421613426946134128e8c61340a8d6133fc60405193849260208401968761324c565b03601f198101835282611fe1565b519020613291565b602081519101209336916132aa565b614df5565b6137b2576124de61343c919897989692966143aa565b60009160009660009860018b01995b86548110156135db5761345f818a8a6132f6565b3561346a8289612a19565b5054036135ca57602061347e828b8b6132f6565b013595600261348d838a612a19565b500154871161359e57866134a091611f31565b99856134ac838a612a19565b506001015463ffffffff16906134c29189614e46565b6134cb91611f31565b95806134d7838a612a19565b50600301558d6134e8838c8c6132f6565b356134f2906120a9565b80546001600160401b03169060010161350a90612185565b61351391614e78565b90549181613520846120d8565b600091825260205260409020549061353791611f31565b918d6135438284612e67565b905461354e91613317565b61271090048084116135855750600193929161356c61357b926120d8565b90600052602052604060002090565b550198949861344b565b63f929853360e01b600052600484905260245260446000fd5b611bb78760026135ae858c612a19565b500154633acfbcd560e11b600052600491909152602452604490565b6305fd57bd60e31b60005260046000fd5b5097965098945098505094505083156137a157600485015484036137975761360560015b866127e6565b83600786015581600886015560038101613620858254611f31565b815554600282015490818111613780575050600401613640828254611f31565b905560038401546136aa906001600160a01b031661368061367361366d6136668461292f565b5460ff1690565b85614ebd565b916001600160a01b031690565b86546001600160a01b0316600080516020615900833981519152546001600160a01b031691614f57565b600080516020615be0833981519152546136cc906001600160a01b031661122b565b84546001600160a01b03169190803b156103dd57604051632851206560e21b81526001600160a01b03939093166004840152602483018490526000908390604490829084905af1801561132e577f3e890f7617fe708b2552fe220901c9fa41fbd0470984b29b88efbd4c2036dd80956137609361375392613765575b505460a81c60ff1690565b936040519485948561332a565b0390a1565b80613774600061377a93611fe1565b80610423565b38613748565b6354baf84560e01b60005260045260245260446000fd5b61360560026135ff565b63ba0d87b560e01b60005260046000fd5b6309bde33960e01b60005260046000fd5b632ae49e7360e01b60005265ffffffffffff1660045260246000fd5b63e650104f60e01b60005260046000fd5b630f5b286d60e11b60005260046000fd5b630ae3c44760e01b60005260046000fd5b908160209103126103dd575160ff811681036103dd5790565b6001600160a01b03811691906138408361439a565b60405163313ce56760e01b815292602084600481845afa93841561132e57600094613990575b5060ff841660068110908115613985575b5061396d57600080516020615c208339815191525492937f3d8adc4d18d36a223b690824a3e95740d80f6643e2aaa8a47a84f4258d9759f3939161376091906139116138dc6138d2600887901c6001600160a01b031661122b565b9560d81c60ff1690565b600080516020615c208339815191528054610100600160a81b03191660089890981b610100600160a81b031697909717909655565b600080516020615c20833981519152805460ff60d81b191660d884901b60ff60d81b16179055604080516001600160a01b03958616815260ff968716602082015294909116908401529290921660608201529081906080820190565b63ec18ce9b60e01b60005260ff841660045260246000fd5b601291501138613877565b6139b391945060203d6020116139ba575b6139ab8183611fe1565b810190613812565b9238613866565b503d6139a1565b6001600160a01b03811660009081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613a5b576001600160a01b031660008181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391906000805160206159208339815191528180a4600190565b50600090565b6001600160a01b0381166000908152600080516020615a00833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615a0083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615ba0833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615960833981519152602052604090205460ff16613a5b576001600160a01b038116600090815260008051602061596083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615ac0833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615a20833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615a2083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615a40833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615c40833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615c4083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615aa0833981519152600080516020615920833981519152600080a4600190565b6000818152600080516020615b40833981519152602090815260408083206001600160a01b038616845290915290205460ff16613d32576000818152600080516020615b40833981519152602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b031690600080516020615920833981519152600080a4600190565b5050600090565b91909182516001600160401b038111611f6f57613d5a81612717845461214b565b6020601f8211600114613d9657819061245c939495600092613d8b5750508160011b916000199060031b1c19161790565b01519050388061273a565b601f19821690613dab84600052602060002090565b9160005b818110613de657509583600195969710613dcd57505050811b019055565b015160001960f88460031b161c19169055388080612786565b9192602060018192868b015181550194019201613daf565b60008051602061598083398151915254600160401b811015611f6f57600181016000805160206159808339815191525560006000805160206159808339815191525482101561243d5760008051602061598083398151915290527f1881c5df5443b563aa79837020da6f3525bbc1de5426f6a8369e84b12b2c1f050155565b600080516020615a8083398151915254600160401b811015611f6f5760018101600080516020615a80833981519152556000600080516020615a808339815191525482101561243d57600080516020615a8083398151915290527f61cb9599a58b4bc1e95f7d63c2591482386071202c54d9ef1ab6c4df8895a4260155565b9493926001600160401b03606093613f27938852166020870152608060408701526080860190610620565b930152565b906001600160401b03613f4683516001600160401b031690565b16156140465781516001600160401b0316916020810192613f708451916040840192835191614ff1565b93613f7a856120a9565b92613f9b613f8f85546001600160401b031690565b6001600160401b031690565b61403557614024817fabe16d0e346dbd6bb822d69ae6eb684c5a85391dac8a689f30b5577cebbcb21495613ff9613fdc61376095516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b614007855160018301613d39565b6002865191015561401788613dfe565b516001600160401b031690565b915192516040519384938885613efc565b630313b28560e01b60005260046000fd5b633d23e4d160e11b60005260046000fd5b6000818152600080516020615b40833981519152602090815260408083206001600160a01b038616845290915290205460ff1615613d32576000818152600080516020615b40833981519152602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b600080a4600190565b3561106e81612339565b903590601e19813603018212156103dd57018035906001600160401b0382116103dd576020019181360383136103dd57565b916141596020926001600160401b039296959660408652604086019161285b565b9416910152565b6001600160401b03614171826140fc565b16156140465760208101906141868282614106565b905015614323576040810135612710811161432357816141e36141c97f6c709e7c783b0ffa2a9da8b3a2bc32ef692f68fac0407a56af322fe370de4240946140fc565b6141dd6141d68785614106565b369161234a565b90614e78565b80946141f9612ec06141f484612107565b615163565b9261422d836000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd011602052604060002090565b90614242613f8f83546001600160401b031690565b1561428b575b5050505061427761425d61145a611455612dfa565b61426686612107565b906001600160e01b03851691615557565b5050604080519182526020820192909252a2565b614317614303846142f461430b956142d16142c77fed457cc56f2f6159a5388260fd7f0309e793291f8c0e089f855f8fd58b6ce36b9988614106565b90600184016126f8565b6142da866140fc565b6001600160401b03166001600160401b0319825416179055565b6142fd87613e7d565b83614106565b9390926140fc565b60405193849384614138565b0390a283388080614248565b63024ef5c960e51b60005260046000fd5b61433c612dfa565b8082036143825750600052600080516020615b208339815191526020526040600020908154156137df57600382015461437157565b630d7b317160e31b60005260046000fd5b90631d56b54b60e31b60005260045260245260446000fd5b6001600160a01b03161561266157565b600080516020615a6083398151915254604051634ce975a360e11b81526004810192909252606090829060249082906001600160a01b03165afa90811561132e57600091614403575b506020015165ffffffffffff1690565b6060813d60601161446c575b8161441c60609383611fe1565b810103126144685781604060209261106e945081519261443b84611f90565b815161444681610a33565b84528482015161445581610a33565b85850152500151604082015291506143f3565b5080fd5b3d915061440f565b919081101561243d576060020190565b3563ffffffff811681036103dd5790565b8054600160401b811015611f6f57610d9191600182018155612a19565b919390949260009260009660009660046144cb86612f87565b01549360005b8281106144e45750505050505050929190565b6144f28184869d9c9d614474565b9760408901359a8b15801561466b575b61465a57878c1061463f5789359060005b8481106146145750614524826120a9565b80546001600160401b03168015614603576145498c916141dd600161454e9501612185565b612e67565b156145f257848d938461456091611f31565b9b6020019e8f9e8f61457190614484565b63ffffffff169061458191613317565b61458a91611f31565b9d61459490614484565b9061459f9185614e46565b6145a891611f31565b9c6145b28861208c565b6145bb90614495565b509182556145c890614484565b60018201906145e6919063ffffffff1663ffffffff19825416179055565b600201556001016144d1565b63435e3df360e11b60005260046000fd5b6307db1be560e41b60005260046000fd5b8261462082898b614474565b351461462e57600101614513565b6376ebe0a360e11b60005260046000fd5b630763c2c360e51b60005260048c9052602488905260446000fd5b633e5fcf1560e21b60005260046000fd5b5063ffffffff61467d60208c01614484565b1615614502565b600080516020615c20833981519152549192916146c36146bd65ffffffffffff60a884901c166001600160a01b03600885901c16615657565b92612f87565b600181015491906147106146df6001600160a01b03851661122b565b60028301546040516370a0823160e01b81526001600160a01b03909116600482015291602090839081906024820190565b0381845afa90811561132e57614738926000926148c4575b5061473290614d41565b90614f10565b600080516020615a608339815191525490929061475d906001600160a01b031661122b565b6040516313520f5760e21b81529590602087600481845afa90811561132e576147946020926147bf996000916148a7575b50615192565b604051635fce2f7360e11b815265ffffffffffff909116600482015297889190829081906024820190565b03915afa92831561132e5761481a61483f95614814614833956148289561480e6148096147ff61483a9b6148459f600091614888575b5060ff8616614732565b9360d81c60ff1690565b614eac565b916157ec565b90611f31565b9060038101549054916157ec565b9360a01c61ffff1690565b61ffff1690565b611f21565b9061577b565b80831161486f5750818111614858575050565b63bb9d933b60e01b60005260045260245260446000fd5b6343aab4a360e11b600052600483905260245260446000fd5b6148a1915060203d602011612e6057612e588183611fe1565b386147f5565b6148be9150843d8611611327576113198183611fe1565b3861478e565b6147329192506148e29060203d602011612e6057612e588183611fe1565b9190614728565b61ffff8116036103dd57565b3561106e816148e9565b600080516020615bc083398151915254600160401b811015611f6f578060016149479201600080516020615bc083398151915255600080516020615bc0833981519152612f6b565b9190916149eb5760a06004918035845560018401614988602083013561496c81610587565b82546001600160a01b0319166001600160a01b03909116178255565b6040820135614996816148e9565b815461ffff918216851b91851b19161790556149da6149b760608301612ae3565b6002860180546001600160a01b0319166001600160a01b03909216919091179055565b608081013560038501550135910155565b612460565b91909160a08060c0830194803584526020810135614a0d81610587565b600180841b0316602085015261ffff6040820135614a2a816148e9565b1660408501526060810135614a3e81610587565b600180841b03166060850152608081013560808501520135910152565b8035612ee081108015614ba6575b614b95576020820190614a8161138261122b84612ae3565b614a9061138260608501612ae3565b60808301358015918215614b82575b5050614b715760a082013515614b6057604082016103e861ffff614ac2836148f5565b1611614b3d57507f4d65ea4765c1c204c4a6882a91a420cb6f1d9fec39f5a6d40e5ebf591c2c056491614afd6113d561122b61376094612ae3565b50614b2f600080516020615bc083398151915254614b1a836148ff565b80611447576001600160e01b0316600061542b565b5050604051918291826149f0565b614b49611bb7916148f5565b6389cb95e960e01b60005261ffff16600452602490565b637f349ee160e11b60005260046000fd5b633fe89cb960e11b60005260046000fd5b614b8d919250613306565b103880614a9f565b63197f247760e01b60005260046000fd5b5061c3508111614a69565b60407f9026541b5a8b912fcc577e1e5d095b812c9d8de7fefbc0280e791126a25e60ac91614bde8161439a565b60008051602061590083398151915280546001600160a01b039283166001600160a01b0319821681179092558351921682526020820152a1565b614c218161439a565b6001600160a01b03811690614c3582615881565b15614c87577f9af05cf8274349906c4818da137d738fd8d36d3b092ceb12e30ce8f0d754974f918160ff614c73614c6d602095614d41565b9261292f565b911660ff19825416179055604051908152a1565b63da562e7d60e01b60005260046000fd5b65ffffffffffff811615614d2057600080516020615c20833981519152805465ffffffffffff60a81b60a884811b9190911665ffffffffffff60a81b198316179092556040805165ffffffffffff9290931c82168352921660208201527f9b9450d02e5838e5d70dfc180234b518f6f6b6c0793775ccd00f87f4d639751d9181908101613760565b63410508c760e01b60005260046000fd5b614d396151af565b6123046151af565b60405163313ce56760e01b81529190602090839060049082906001600160a01b03165afa91821561132e57600092614d98575b5060ff821660128111614d845750565b63fd91cbed60e01b60005260045260246000fd5b614db291925060203d6020116139ba576139ab8183611fe1565b9038614d74565b60001981019190821161041e57565b9190820391821161041e57565b6000526000805160206159c0833981519152602052604060002054151590565b929091906000915b8451831015614e3e57604060019160009060208660051b8901015190818110600014614e32578252602052205b920191614dfd565b90825260205220614e2a565b915092501490565b91614e5d9063ffffffff64496cebb8009316613317565b614e688282856157ec565b92091515810180911161041e5790565b90614ea66133fc916040519283916001600160401b0360208401961686526040808401526060830190610620565b51902090565b60ff16604d811161041e57600a0a90565b9060ff1680601214612fde5780601210614ef15760120360ff811161041e5761106e91614eeb600192614eac565b906153a0565b601119019060ff821161041e57614f0a61106e92614eac565b90613317565b9060ff1660128114612fde5760128110614f3f576011190160ff811161041e5761106e91614eeb600092614eac565b6012039060ff821161041e57614f0a61106e92614eac565b6040516323b872dd60e01b60208083019182526001600160a01b0394851660248401529490931660448201526064808201959095529384529260009190614f9f608482611fe1565b519082855af115612923576000513d614fe857506001600160a01b0381163b155b614fc75750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415614fc0565b9161502191614ea6916040519384926001600160401b036020850197168752606060408501526080840190610620565b90606083015203601f198101835282611fe1565b8054801561505e57600019019061504c828261280a565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b60008181526000805160206159c08339815191526020526040902054908115613d325760001982019082821161041e57600080516020615b008339815191525460001981019390841161041e578383600095615108950361510e575b5050506150ea600080516020615b00833981519152615035565b6000805160206159c083398151915290600052602052604060002090565b55600190565b6150ea6151549161513d61513361515a95600080516020615b0083398151915261280a565b90549060031b1c90565b928391600080516020615b0083398151915261280a565b90612442565b553880806150d0565b80549081615172575050600090565b8160001981011161041e5760005260001990602060002001015460201c90565b65ffffffffffff6000199116019065ffffffffffff821161041e57565b60ff600080516020615c008339815191525460401c16156151cc57565b631afcd79f60e31b60005260046000fd5b600181111561106e57806001600160801b8210156152fe575b6152a461529a61529061528661527c6152726152616152ab9760046152b09a600160401b8110156152f1575b6401000000008110156152e4575b620100008110156152d7575b6101008110156152ca575b60108110156152bd575b10156152b5575b60030260011c90565b61526b818b612697565b0160011c90565b61526b818a612697565b61526b8189612697565b61526b8188612697565b61526b8187612697565b61526b8186612697565b8093612697565b821190565b900390565b60011b615258565b60041c9160021b91615251565b60081c9160041b91615247565b60101c9160081b9161523c565b60201c9160101b91615230565b60401c9160201b91615222565b50506152b06152ab6152a461529a61529061528661527c6152726152616153258a60801c90565b9850600160401b97506151f69650505050505050565b91905b83821061534b5750505090565b9091928083169080841860011c820180921161041e578460005263ffffffff82602060002001541663ffffffff84161060001461538c5750925b919061533e565b9392506001810180911161041e5791615385565b906001806153af8382866157ec565b946153b981610609565b161491826153d2575b50501515810180911161041e5790565b90809250156126a15760019009151538806153c2565b8054600160401b811015611f6f576154059160018201815561280a565b6149eb57815160209283015190921b63ffffffff191663ffffffff909216919091179055565b6000805160206159a083398151915254919291801561552d5761545061548791614db9565b6000805160206159a08339815191526000527f2060c037175d92fda9c6bae663cfb46d241cf6f66cac38481ca19c403ebfb7920190565b9081546154a161549a8263ffffffff1690565b9160201c90565b9263ffffffff80841692169180831161551c578692036154db576154d792509063ffffffff82549181199060201b169116179055565b9190565b50506154d7906154f86154ec612012565b63ffffffff9092168252565b6001600160e01b03851660208201525b6000805160206159a08339815191526153e8565b632520601d60e01b60005260046000fd5b506155519061553d6154ec612012565b6001600160e01b0384166020820152615508565b60009190565b805492939280156155ec5761556e61557b91614db9565b8260005260206000200190565b8054602081901c9363ffffffff9182169291811680841161551c578793036155ba57506154d792509063ffffffff82549181199060201b169116179055565b9150506154d7916155d86155cc612012565b63ffffffff9093168352565b6001600160e01b03861660208301526153e8565b5090615551916155fd6155cc612012565b6001600160e01b03851660208301526153e8565b51906001600160501b03821682036103dd57565b908160a09103126103dd5761563981615611565b9160208201519160408101519161106e608060608401519301615611565b604051633fabe5a360e21b8152919060a090839060049082906001600160a01b03165afa91821561132e576000928380928192615740575b50600085131561572a578215615719576001600160501b0381166001600160501b038316106156f65750506156c48142614dc8565b65ffffffffffff8316106156d757505090565b6385ada3f360e01b60005260045265ffffffffffff1660245260446000fd5b630cb58a9360e31b6000526001600160501b039081166004521660245260446000fd5b63b3e6505f60e01b60005260046000fd5b633c30523f60e01b600052600485905260246000fd5b9250505061576791925060a03d60a011615774575b61575f8183611fe1565b810190615625565b929493909291503861568f565b503d615755565b80820290600019838209908280831092039180830392146157e1578161271011156157da577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9193612710910990828211900360fc1b910360041c170290565b60116158ee565b506127109250500490565b91818302916000198185099383808610950394808603951461587457848311156158675790829109816000038216809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b60116003841502186158ee565b50509061106e9250612697565b806000526000805160206159c083398151915260205260406000205415600014613a5b576158bd81600080516020615b00833981519152612822565b600080516020615b0083398151915254906000526000805160206159c0833981519152602052604060002055600190565b634e487b716000526020526024601cfdfe89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0012f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd004fb3f6e6e654f6130d3f2fa1f8ac1a8341f2fb9e0730e1425ef2cfee0612ce99389fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00e89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00a89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00889fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd005b16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c263f10a9fca1980f9ac4a56a776ebe74bab62acb2d47edad7c1e0e938757dc0768bf109b95a5c15fb2bb99041323c27d15f8675e11bf7420a1cd6ad64c394f4689fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd010b92d52e77ebaa0cae5c23e882d85609efbcb44029214147dd132daf9ef1018af850d585eb7f024ccee5e68e55f2c26cc72e1e6ee456acf62135757a5eb9d4a1089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00389fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00789fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00b02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0149b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177589fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00989fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd002f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd013985e7e44dfcb208cb67a8ab5f4ddea68569700462a8bdd41960667c1dc173537a26469706673582212202f5793a768ff3c128ced0a1dd18aaa8ba198242d40cf3efbc94116561556dc7464736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"optimizer":{"enabled":true,"runs":100},"outputSelection":{"*":{"":["*"],"*":["*"]}},"viaIR":true},"optimization_runs":100,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-09-30T02:54:30.693577Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6080806040523460d2577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b604051615c9590816100d88239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880604d565b63f92ee8a960e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a71461038757806304acf36814610382578063061831101461037d578063113e6e76146103785780631584410a146103735780631b0eeb7e1461036e5780631c5f5ceb146103695780631c87ad931461036457806322e359ad1461035f578063248a9ca31461035a57806325d8c1c514610355578063271de2ae146103505780632aa304d71461034b5780632f2ff15d1461034657806331a539b914610341578063325d62821461033c578063363768101461033757806336568abe1461033257806336807c631461032d57806336b50ff81461032857806342e53fcf146103235780634a2cfb541461031e5780634e37695a1461031957806352c9926014610314578063582670521461030f578063595fdd671461030a5780635d7b0cad14610305578063697209791461030057806375b238fc146102fb578063764e64cf146102f657806387a0611d146102f15780638b9c2cbf146102ec57806391d14854146102e757806392390479146102e257806392bbcf66146102dd5780639ae38bca146102d8578063a217fddf146102d3578063a25aa00b146102ce578063bc80feb3146102c9578063c0cb9233146102c4578063c78ef28c146102bf578063c7fb139b146102ba578063c81cbaa1146102b5578063cdb0cadb146102b0578063d3cc14ed146102ab578063d547741f146102a6578063db989a9f146102a1578063e33f823b1461029c578063e89ac07b14610297578063ea49248c14610292578063ef0595f51461028d578063f30554b514610288578063f779c85d14610283578063fbfa77cf1461027e5763fe1b61231461027957600080fd5b611d88565b611d52565b611d31565b611cfe565b611c2f565b611bbb565b611a71565b611a32565b611a05565b6119d1565b61191a565b6117f4565b6117cb565b611712565b6116e9565b611675565b611648565b611617565b6115fb565b6115ce565b611573565b61153d565b6114da565b611344565b6111ae565b611129565b611100565b611071565b61102b565b610f71565b610ef9565b610ece565b610e33565b610e0a565b610dd4565b610d95565b610d4b565b610d01565b610c6d565b610bb9565b610b8f565b610b28565b610afb565b610a43565b610962565b610944565b6108bf565b6107f1565b61071e565b6105a7565b610551565b610468565b61042e565b6103e2565b346103dd5760203660031901126103dd5760043563ffffffff60e01b81168091036103dd57602090637965db0b60e01b81149081156103cc575b506040519015158152f35b6301ffc9a760e01b149050386103c1565b600080fd5b346103dd5760203660031901126103dd576004356103fe612dfa565b906001820180921161041e5760209161041691612e67565b604051908152f35b611efd565b60009103126103dd57565b346103dd5760003660031901126103dd57600080516020615c208339815191525460405160089190911c6001600160a01b03168152602090f35b346103dd5760203660031901126103dd5761054d61049060043561048a612021565b50612f87565b60046040519161049f83611f54565b8054835260018101546001600160a01b038116602085015260a01c61ffff16604084015260028101546104e5906001600160a01b03166001600160a01b03166060850152565b60038101546080840152015460a08201526040519182918291909160a08060c083019480518452600180831b03602082015116602085015261ffff6040820151166040850152600180831b036060820151166060850152608081015160808501520151910152565b0390f35b346103dd5760003660031901126103dd57602065ffffffffffff600080516020615c208339815191525460a81c16604051908152f35b6001600160a01b038116036103dd57565b606435906105a582610587565b565b346103dd5760203660031901126103dd5760206105d76004356105c981610587565b6001600160a01b0316614dd5565b6040519015158152f35b634e487b7160e01b600052602160045260246000fd5b9060028210156106045752565b6105e1565b6004111561060457565b9061061d82610609565b52565b919082519283825260005b84811061064c575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161062b565b602080825282516001600160a01b031690820152610687602083015160408301906105f7565b61069960408301516060830190610613565b60608201516001600160a01b031660808201526101806101606106cb60808501518360a08601526101a0850190610620565b60a08501516001600160a01b031660c08501529360c081015160e085015260e081015161010085015261010081015161012085015261012081015161014085015261014081015182850152015191015290565b346103dd5760203660031901126103dd57600435600061016060405161074381611f74565b828152826020820152826040820152826060820152606060808201528260a08201528260c08201528260e0820152826101008201528261012082015282610140820152015260005260008051602061594083398151915260205261054d6107ad6040600020612227565b60405191829182610661565b602081526001600160401b038251166020820152606060406107e8602085015183838601526080850190610620565b93015191015290565b346103dd5760203660031901126103dd5760043560006040805161081481611f90565b8281526060602082015201526000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00660205261054d604060002060026040519161085e83611f90565b6001600160401b03815416835261087760018201612185565b602084015201546040820152604051918291826107b9565b9181601f840112156103dd578235916001600160401b0383116103dd576020808501948460051b0101116103dd57565b346103dd5760603660031901126103dd576004356024356001600160401b0381116103dd57366023820112156103dd578060040135906001600160401b0382116103dd573660248360061b830101116103dd57604435916001600160401b0383116103dd5761094293610938602494369060040161088f565b94909301906122e7565b005b346103dd5760203660031901126103dd576020610416600435612318565b346103dd5760203660031901126103dd5760043561097e612021565b50600052600080516020615b2083398151915260205261054d604060002065ffffffffffff6005604051926109b284611f54565b805484526001810154602085015260028101546040850152600381015460608501526004810154608085015201541660a08201526040519182918291909160a065ffffffffffff8160c08401958051855260208101516020860152604081015160408601526060810151606086015260808101516080860152015116910152565b65ffffffffffff8116036103dd57565b346103dd5760203660031901126103dd57600435610a6081610a33565b610a686130ca565b65ffffffffffff8116906170808211610ae057600080516020615b60833981519152805465ffffffffffff19811690931790556040805165ffffffffffff93841681529190921660208201527fc5a463d4ef3011e309d848d389bb7b7c23889c0611844319ea2c43c9543b2ac691819081015b0390a1005b50631f1c218960e01b60005260045261708060245260446000fd5b346103dd5760203660031901126103dd57610942600435610b1b81610587565b610b23613118565b61382b565b346103dd5760403660031901126103dd57610942602435600435610b4b82610587565b610b5c610b5782612318565b613202565b613c9d565b60206003198201126103dd576004356001600160401b0381116103dd57606090600401809203126103dd5790565b346103dd576020610416610bb4610ba536610b61565b610bad6130ca565b3690612390565b613f2c565b346103dd5760203660031901126103dd57600435610bd681610587565b610bde6130ca565b6001600160a01b0316610bf081615074565b15610c225760207f140755d6e5a015c6a602fd931764198cf5875820d73c092baf578bee102fd6ed91604051908152a1005b63216187cb60e21b60005260046000fd5b602060408183019282815284518094520192019060005b818110610c575750505090565b8251845260209384019390920191600101610c4a565b346103dd5760203660031901126103dd576004356000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00c602052604060002060405190816020825491828152019160005260206000209060005b818110610ceb5761054d85610cdf81870382611fe1565b60405191829182610c33565b8254845260209093019260019283019201610cc8565b346103dd5760403660031901126103dd57600435602435610d2181610587565b336001600160a01b03821603610d3a5761094291614057565b63334bd91960e11b60005260046000fd5b346103dd5760003660031901126103dd57602060405160128152f35b60206003198201126103dd57600435906001600160401b0382116103dd57610d919160040161088f565b9091565b346103dd57610da336610d67565b90610dac6130ca565b60005b828110610db857005b80610dce610dc9600193868661241b565b614160565b01610daf565b346103dd5760003660031901126103dd57600080516020615be0833981519152546040516001600160a01b039091168152602090f35b346103dd5760003660031901126103dd576020604051600080516020615ac08339815191528152f35b346103dd5760203660031901126103dd57600435610e4f6130ca565b7f102f71bf03a442e06446151ebf1aa14ee8a00abda0e6e23db350bdadb9c04a53610ec9610e7c83614334565b5483600052600080516020615b2083398151915260205260006005604082208281558260018201558260028201558260038201558260048201550155604051918291829190602083019252565b0390a2005b346103dd5760003660031901126103dd576020600080516020615ae083398151915254604051908152f35b346103dd5760003660031901126103dd57610f12612021565b50610f1b612dfa565b6001810180911161041e5761049061054d91612f87565b9181601f840112156103dd578235916001600160401b0383116103dd57602080850194606085020101116103dd57565b60a4359060028210156103dd57565b346103dd5760c03660031901126103dd57600435610f8e81610587565b602435610f9a81610587565b6044356001600160401b0381116103dd57366023820112156103dd578060040135926001600160401b0384116103dd5736602485840101116103dd57610fde610598565b92608435936001600160401b0385116103dd5761054d9561100661101b963690600401610f32565b9490936024611013610f62565b970191612476565b6040519081529081906020820190565b346103dd5761094261103c36610b61565b610dc96130ca565b6060602061106e938184526001600160401b03815116828501520151916040808201520190610620565b90565b346103dd5760203660031901126103dd576004356060602060405161109581611fab565b6000815201526000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd01160205261054d60406000206110ef6001604051926110dc84611fab565b6001600160401b03815416845201612185565b602082015260405191829182611044565b346103dd5760003660031901126103dd576020604051600080516020615ba08339815191528152f35b346103dd5760003660031901126103dd57611142612968565b60405180916020820160208352815180915260206040840192019060005b81811061116e575050500390f35b82516001600160a01b0316845285945060209384019390920191600101611160565b60809060031901126103dd5760043590602435906044359060643590565b346103dd576111bc36611190565b90916111c66130ca565b8015611333576111d584614334565b926112056111f7600080516020615b608339815191525465ffffffffffff1690565b65ffffffffffff42166128f0565b906004602061123761122b600080516020615a608339815191525460018060a01b031690565b6001600160a01b031690565b604051632c3ca22b60e11b815292839182905afa801561132e5765ffffffffffff916000916112ff575b501665ffffffffffff831610156112ee576112d1610ec99260057f9edc562117c283540e3b0753d6a0a669589c7897e1ba29a9aaefeb912c418b16976112a885898c614684565b868155876001820155846002820155019065ffffffffffff1665ffffffffffff19825416179055565b604051938493846040919493926060820195825260208201520152565b63ab6d660760e01b60005260046000fd5b611321915060203d602011611327575b6113198183611fe1565b81019061290e565b38611261565b503d61130f565b612923565b639dd854d360e01b60005260046000fd5b346103dd5760c03660031901126103dd57600061135f6130ca565b600435612ee0811080156114cf575b6114c05761138761138261122b6024612ae3565b61439a565b6113946113826064612ae3565b60843580159182156114ad575b505061149e5760a4351561148f576103e861ffff6113bf60446148f5565b1611611469576113da6113d561122b6024612ae3565b614d41565b5061140f600080516020615bc0833981519152546113f860046148ff565b806114475782905b6001600160e01b03169061542b565b50507f4d65ea4765c1c204c4a6882a91a420cb6f1d9fec39f5a6d40e5ebf591c2c0564604051806114416004826149f0565b0390a180f35b61146361145a611455612dfa565b611f13565b63ffffffff1690565b90611400565b61148c61147660446148f5565b6389cb95e960e01b835261ffff16600452602490565b90fd5b637f349ee160e11b8152600490fd5b633fe89cb960e11b8152600490fd5b6114b8919250613306565b1038806113a1565b63197f247760e01b8252600482fd5b5061c350811161136e565b346103dd5760403660031901126103dd57602060ff61153160243560043561150182610587565b600052600080516020615b40833981519152845260406000209060018060a01b0316600052602052604060002090565b54166040519015158152f35b346103dd5760003660031901126103dd57600080516020615900833981519152546040516001600160a01b039091168152602090f35b346103dd5760403660031901126103dd57600435602435906000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00d6020526040600020906000526020526020604060002054604051908152f35b346103dd5760203660031901126103dd576109426004356115ee81610587565b6115f6613118565b614bb1565b346103dd5760003660031901126103dd57602060405160008152f35b346103dd5760003660031901126103dd57602060ff600080516020615c208339815191525460d81c16604051908152f35b346103dd5760203660031901126103dd5761094260043561166881610587565b6116706130ca565b614c18565b346103dd5760003660031901126103dd57604051600080516020615a80833981519152548082526020820190600080516020615a8083398151915260005260206000209060005b8181106116d35761054d85610cdf81870382611fe1565b82548452602090930192600192830192016116bc565b346103dd5760003660031901126103dd576020604051600080516020615aa08339815191528152f35b346103dd5761172036610d67565b61172861308e565b611730613166565b60005b818110611751576109426001600080516020615b8083398151915255565b61175c81838561241b565b359061176981848661241b565b602081013590601e19813603018212156103dd57018035906001600160401b0382116103dd576020018160061b360381136103dd576001936117c5926117bd6117b386898b61241b565b60408101906129cd565b93909261334e565b01611733565b346103dd5760003660031901126103dd576020604051600080516020615a408339815191528152f35b346103dd5760203660031901126103dd576004356118106131b4565b600081815260008051602061594083398151915260205260409020805490916001600160a01b038216156118a75760ff8260a81c1661184e81610609565b6118965760ff60a81b19909116600360a81b179091556040519081527f091116832d5c5cf537cbf8f22b48e141643e4f959373984adaa4962cec96cb96908060208101610adb565b635d12a4a360e11b60005260046000fd5b63af61069360e01b60005260046000fd5b602060408183019282815284518094520192019060005b8181106118dc5750505090565b90919260206080600192606087518051835263ffffffff858201511685840152604081015160408401520151606082015201940191019190916118cf565b346103dd5760203660031901126103dd576004356000526000805160206159e08339815191526020526040600020805461195381612a02565b916119616040519384611fe1565b818352602083019060005260206000206000915b83831061198a576040518061054d87826118b8565b6004602060019260405161199d81611fc6565b8554815263ffffffff8587015416838201526002860154604082015260038601546060820152815201920192019190611975565b346103dd5760403660031901126103dd576109426024356004356119f482610587565b611a00610b5782612318565b614057565b346103dd5760203660031901126103dd57610942600435611a2581610a33565b611a2d613118565b614c98565b346103dd5760403660031901126103dd576060611a53602435600435612a35565b6040805193845260208401929092526001600160a01b031690820152f35b346103dd57611a7f36611190565b9091611a89613166565b801561133357611a97612dfa565b93848103611ba15750611aa984612052565b54611b9057611acf6111f7600080516020615b608339815191525465ffffffffffff1690565b600080516020615a6083398151915254600490602090611af7906001600160a01b031661122b565b604051632c3ca22b60e11b815292839182905afa801561132e5765ffffffffffff91600091611b71575b501665ffffffffffff821610156112ee57836112d1610ec992611b667f9edc562117c283540e3b0753d6a0a669589c7897e1ba29a9aaefeb912c418b1697878a614684565b60056112a889612052565b611b8a915060203d602011611327576113198183611fe1565b38611b21565b6383a1dec160e01b60005260046000fd5b631d56b54b60e31b600052600452602484905260445b6000fd5b346103dd5760003660031901126103dd5760405160008051602061598083398151915254808252602082019060008051602061598083398151915260005260206000209060005b818110611c195761054d85610cdf81870382611fe1565b8254845260209093019260019283019201611c02565b346103dd57611c3d36610d67565b90611c46612dfa565b9160005b818110611c5357005b611c5e818385612ad3565b3590611c698261206f565b8054909290611c806001600160a01b03821661122b565b156118a75760a81c60ff16611c9481610609565b611896578560098401541015611ced57825460ff60a81b1916600360a81b179092556001917f091116832d5c5cf537cbf8f22b48e141643e4f959373984adaa4962cec96cb9690611ce49061101b565b0390a101611c4a565b63796c85f360e01b60005260046000fd5b346103dd5760003660031901126103dd57602065ffffffffffff600080516020615b608339815191525416604051908152f35b346103dd5760403660031901126103dd576020610416602435600435612e67565b346103dd5760003660031901126103dd57600080516020615a60833981519152546040516001600160a01b039091168152602090f35b346103dd5760203660031901126103dd576004356001600160401b0381116103dd5761026060031982360301126103dd57600080516020615c0083398151915254906001600160401b03611df460ff604085901c1615611de7565b1590565b936001600160401b031690565b1680159081611ef5575b6001149081611eeb575b159081611ee2575b50611ed157611e599082611e4c60016001600160401b0319600080516020615c00833981519152541617600080516020615c0083398151915255565b611eac575b600401612b0c565b611e5f57005b600080516020615c00833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2908060208101610adb565b600080516020615c00833981519152805460ff60401b1916600160401b179055611e51565b63f92ee8a960e01b60005260046000fd5b90501538611e10565b303b159150611e08565b839150611dfe565b634e487b7160e01b600052601160045260246000fd5b906001820180921161041e57565b6127100190816127101161041e57565b9190820180921161041e57565b634e487b7160e01b600052604160045260246000fd5b60c081019081106001600160401b03821117611f6f57604052565b611f3e565b61018081019081106001600160401b03821117611f6f57604052565b606081019081106001600160401b03821117611f6f57604052565b604081019081106001600160401b03821117611f6f57604052565b608081019081106001600160401b03821117611f6f57604052565b90601f801991011681019081106001600160401b03821117611f6f57604052565b604051906105a561018083611fe1565b604051906105a5604083611fe1565b6040519061202e82611f54565b600060a0838281528260208201528260408201528260608201528260808201520152565b600052600080516020615b20833981519152602052604060002090565b600052600080516020615940833981519152602052604060002090565b6000526000805160206159e0833981519152602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd006602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00d602052604060002090565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00f602052604060002090565b60028210156106045752565b61061d82610609565b90600182811c9216801561217b575b602083101461216557565b634e487b7160e01b600052602260045260246000fd5b91607f169161215a565b90604051918260008254926121998461214b565b808452936001811690811561220557506001146121be575b506105a592500383611fe1565b90506000929192526020600020906000915b8183106121e95750509060206105a592820101386121b1565b60209193508060019154838589010152019101909184926121d0565b9050602092506105a594915060ff191682840152151560051b820101386121b1565b906009612232612002565b83546001600160a01b0381168252909390612271906122689061225f60a082901c60ff1660208901612136565b60a81c60ff1690565b60408601612142565b60018101546001600160a01b0316606085015261229060028201612185565b608085015260038101546001600160a01b031660a0850152600481015460c0850152600581015460e08501526006810154610100850152600781015461012085015260088101546101408501520154610160830152565b90612304949392916122f761308e565b6122ff613166565b61334e565b6001600080516020615b8083398151915255565b600052600080516020615b4083398151915260205260016040600020015490565b6001600160401b038116036103dd57565b9291926001600160401b038211611f6f5760405191612373601f8201601f191660200184611fe1565b8294818452818301116103dd578281602093846000960137010152565b9190916060818403126103dd57604051906123aa82611f90565b819381356123b781612339565b835260208201356001600160401b0381116103dd5782019181601f840112156103dd576123ee60409392836020869535910161234a565b60208501520135910152565b61106e903690612390565b634e487b7160e01b600052603260045260246000fd5b919081101561243d5760051b81013590605e19813603018212156103dd570190565b612405565b9161245c9183549060031b91821b91600019901b19161790565b9055565b634e487b7160e01b600052600060045260246000fd5b9396919596949290946124876131b4565b6124908561439a565b6124998661439a565b8115612661578715612650576124c2611de36124bd6001600160a01b03841661122b565b614dd5565b610c22576124d1611455612dfa565b936124e96124de866143aa565b65ffffffffffff1690565b801561263f578590600080516020615ae0833981519152549a61250b8c612672565b600080516020615ae083398151915255612525938c6144b2565b8261253291949294612697565b938661253d8c61206f565b80546001600160a01b0319166001600160a01b038b161781556001810180546001600160a01b0319166001600160a01b038d16179055612581838d600284016126f8565b6003810180546001600160a01b0319166001600160a01b0386161790558460048201558560058201558660068201556125ba88826127c2565b805460ff60a81b19168155600901558a6125fd886000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00c602052604060002090565b9061260791612822565b604051998a99612618998d8c61287c565b037f09ad29fb5a3daab22928c7284f1bbea8855c2ff7c3e3e5345576d9d840724eb191a190565b634f08daf360e11b60005260046000fd5b63a1d9979360e01b60005260046000fd5b63f6b2911f60e01b60005260046000fd5b600019811461041e5760010190565b634e487b7160e01b600052601260045260246000fd5b81156126a1570490565b612681565b601f82116126b357505050565b6000526020600020906020601f840160051c830193106126ee575b601f0160051c01905b8181106126e2575050565b600081556001016126d7565b90915081906126ce565b9092916001600160401b038111611f6f5761271d81612717845461214b565b846126a6565b6000601f821160011461275a57819061245c93949560009261274f575b50508160011b916000199060031b1c19161790565b01359050388061273a565b601f1982169461276f84600052602060002090565b91805b8781106127aa575083600195969710612790575b505050811b019055565b0135600019600384901b60f8161c19169055388080612786565b90926020600181928686013581550194019101612772565b90600281101561060457815460ff60a01b191660a09190911b60ff60a01b16179055565b906127f081610609565b815460ff60a81b191660a89190911b60ff60a81b16179055565b805482101561243d5760005260206000200190600090565b805490600160401b821015611f6f578161284491600161245c9401815561280a565b819391549060031b91821b91600019901b19161790565b908060209392818452848401376000828201840152601f01601f1916010190565b979390946128ec97936128c2936101209b979e9d9c989e8b5260018060a01b031660208b015260018060a01b031660408a015261014060608a015261014089019161285b565b6001600160a01b03909a16608087015260a086015260c085015260e08401526101008301906105f7565b0152565b9065ffffffffffff8091169116019065ffffffffffff821161041e57565b908160209103126103dd575161106e81610a33565b6040513d6000823e3d90fd5b6001600160a01b031660009081527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0126020526040902090565b60405190600080516020615b00833981519152548083528260208101600080516020615b0083398151915260005260206000209260005b8181106129b45750506105a592500383611fe1565b845483526001948501948794506020909301920161299f565b903590601e19813603018212156103dd57018035906001600160401b0382116103dd57602001918160051b360383136103dd57565b6001600160401b038111611f6f5760051b60200190565b805482101561243d5760005260206000209060021b0190600090565b600092600092600092806000526000805160206159e083398151915260205260406000209081549260005b848110612a6e575050505050565b81612a798286612a19565b505414612a8857600101612a60565b97505092935093505060005260008051602061594083398151915260205260016003612abe604060002095600987015495612a19565b5001549301549192916001600160a01b031690565b919081101561243d5760051b0190565b3561106e81610587565b908160209103126103dd575161106e81610587565b3561106e81610a33565b90612b1c61138261122b84612ae3565b6040820191612b3061138261122b85612ae3565b60c08101612b4061138282612ae3565b60e08201612b5061138282612ae3565b610100830191612b6261138284612ae3565b610120840191612b7461138284612ae3565b612c0b612bdc610140870198612b8c6113828b612ae3565b612b946151af565b612b9c614d31565b612bd7612ba889612ae3565b600080516020615a6083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612ae3565b600080516020615be083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60046020612c1b61122b88612ae3565b6040516338d52e0f60e01b815292839182905afa90811561132e57612c7691612c4c91600091612dbc575b50614d41565b60ff1660ff19600080516020615c20833981519152541617600080516020615c2083398151915255565b612c856115f660208701612ae3565b612c94611a2d60808701612b02565b612ca3610b2360608701612ae3565b60005b60a08601612cb481886129cd565b9050821015612ce05790612cda611670612bd783612cd46001968c6129cd565b90612ad3565b01612ca6565b5050919490929560005b6101608601612cf981886129cd565b9050821015612d225790612d1c610dc982612d166001958b6129cd565b9061241b565b01612cea565b5050919490929560005b6101808601612d3b81886129cd565b9050821015612d675790612d60610bb4612d5b83612d166001968c6129cd565b6123fa565b5001612d2c565b505090612d9f612daa612daf93612d9f612da5612db99a612d9f612d9a612d9f9a9b9e612bd76101a0612db49f01614a5b565b6139c1565b50612ae3565b613a61565b613af0565b613b7f565b613c0e565b50565b612dde915060203d602011612de4575b612dd68183611fe1565b810190612aed565b38612c46565b503d612dcc565b908160209103126103dd575190565b600080516020615a608339815191525460405162c080c360e31b815290602090829060049082906001600160a01b03165afa90811561132e57600091612e3e575090565b61106e915060203d602011612e60575b612e588183611fe1565b810190612deb565b503d612e4e565b6000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00f60205263ffffffff604060002091169060009181549083829160058411612ee8575b612eb893508461533b565b80612ecc5750505b6001600160e01b031690565b612ed590614db9565b908252602082200190505460201c612ec0565b9192612ef3816151dd565b810390811161041e57612eb89385875263ffffffff82602089200154168410600014612f20575091612ead565b929150612f2c90611f13565b90612ead565b600080516020615bc08339815191525481101561243d57600080516020615bc08339815191526000526005602060002091020190600090565b805482101561243d576000526005602060002091020190600090565b63ffffffff1660006000805160206159a08339815191525481928160058111613011575b5090612fde93612fc9926000805160206159a083398151915261533b565b80612fe257505b6001600160e01b0316612f32565b5090565b906020612ff161300c93614db9565b916000805160206159a0833981519152815220015460201c90565b612fd0565b9361301b856151dd565b850394851161041e576000805160206159a083398151915284527f2060c037175d92fda9c6bae663cfb46d241cf6f66cac38481ca19c403ebfb792850154612fde95612fc994909163ffffffff1684101561307c5750915b91925093612fab565b92915061308890611f13565b90613073565b6002600080516020615b8083398151915254146130b9576002600080516020615b8083398151915255565b633ee5aeb560e01b60005260046000fd5b336000908152600080516020615c40833981519152602052604090205460ff16156130f157565b63e2517d3f60e01b60005233600452600080516020615aa083398151915260245260446000fd5b336000908152600080516020615a00833981519152602052604090205460ff161561313f57565b63e2517d3f60e01b60005233600452600080516020615ba083398151915260245260446000fd5b336000908152600080516020615a20833981519152602052604090205460ff161561318d57565b63e2517d3f60e01b60005233600452600080516020615a4083398151915260245260446000fd5b336000908152600080516020615960833981519152602052604090205460ff16156131db57565b63e2517d3f60e01b60005233600452600080516020615ac083398151915260245260446000fd5b6000818152600080516020615b408339815191526020908152604080832033845290915290205460ff16156132345750565b63e2517d3f60e01b6000523360045260245260446000fd5b90815260406020820181905281018390526060019160005b8181106132715750505090565b823584526020808401359085015260409384019390920191600101613264565b90604051916020830152602082526105a5604083611fe1565b9291906132b681612a02565b936132c46040519586611fe1565b602085838152019160051b81019283116103dd57905b8282106132e657505050565b81358152602091820191016132da565b919081101561243d5760061b0190565b908160050291600583040361041e57565b8181029291811591840414171561041e57565b9081526080810194939260609261334081610609565b602083015260408201520152565b9394919061335b8561206f565b80549096906001600160a01b038116156118a75760a81c60ff1661337e81610609565b6118965761338a612dfa565b9660098101978854809103613801576133a28861208c565b92835486036137f0576133b482612052565b9788549081156137df5760058a015465ffffffffffff164281116137c3575091611de391613421613426946134128e8c61340a8d6133fc60405193849260208401968761324c565b03601f198101835282611fe1565b519020613291565b602081519101209336916132aa565b614df5565b6137b2576124de61343c919897989692966143aa565b60009160009660009860018b01995b86548110156135db5761345f818a8a6132f6565b3561346a8289612a19565b5054036135ca57602061347e828b8b6132f6565b013595600261348d838a612a19565b500154871161359e57866134a091611f31565b99856134ac838a612a19565b506001015463ffffffff16906134c29189614e46565b6134cb91611f31565b95806134d7838a612a19565b50600301558d6134e8838c8c6132f6565b356134f2906120a9565b80546001600160401b03169060010161350a90612185565b61351391614e78565b90549181613520846120d8565b600091825260205260409020549061353791611f31565b918d6135438284612e67565b905461354e91613317565b61271090048084116135855750600193929161356c61357b926120d8565b90600052602052604060002090565b550198949861344b565b63f929853360e01b600052600484905260245260446000fd5b611bb78760026135ae858c612a19565b500154633acfbcd560e11b600052600491909152602452604490565b6305fd57bd60e31b60005260046000fd5b5097965098945098505094505083156137a157600485015484036137975761360560015b866127e6565b83600786015581600886015560038101613620858254611f31565b815554600282015490818111613780575050600401613640828254611f31565b905560038401546136aa906001600160a01b031661368061367361366d6136668461292f565b5460ff1690565b85614ebd565b916001600160a01b031690565b86546001600160a01b0316600080516020615900833981519152546001600160a01b031691614f57565b600080516020615be0833981519152546136cc906001600160a01b031661122b565b84546001600160a01b03169190803b156103dd57604051632851206560e21b81526001600160a01b03939093166004840152602483018490526000908390604490829084905af1801561132e577f3e890f7617fe708b2552fe220901c9fa41fbd0470984b29b88efbd4c2036dd80956137609361375392613765575b505460a81c60ff1690565b936040519485948561332a565b0390a1565b80613774600061377a93611fe1565b80610423565b38613748565b6354baf84560e01b60005260045260245260446000fd5b61360560026135ff565b63ba0d87b560e01b60005260046000fd5b6309bde33960e01b60005260046000fd5b632ae49e7360e01b60005265ffffffffffff1660045260246000fd5b63e650104f60e01b60005260046000fd5b630f5b286d60e11b60005260046000fd5b630ae3c44760e01b60005260046000fd5b908160209103126103dd575160ff811681036103dd5790565b6001600160a01b03811691906138408361439a565b60405163313ce56760e01b815292602084600481845afa93841561132e57600094613990575b5060ff841660068110908115613985575b5061396d57600080516020615c208339815191525492937f3d8adc4d18d36a223b690824a3e95740d80f6643e2aaa8a47a84f4258d9759f3939161376091906139116138dc6138d2600887901c6001600160a01b031661122b565b9560d81c60ff1690565b600080516020615c208339815191528054610100600160a81b03191660089890981b610100600160a81b031697909717909655565b600080516020615c20833981519152805460ff60d81b191660d884901b60ff60d81b16179055604080516001600160a01b03958616815260ff968716602082015294909116908401529290921660608201529081906080820190565b63ec18ce9b60e01b60005260ff841660045260246000fd5b601291501138613877565b6139b391945060203d6020116139ba575b6139ab8183611fe1565b810190613812565b9238613866565b503d6139a1565b6001600160a01b03811660009081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613a5b576001600160a01b031660008181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391906000805160206159208339815191528180a4600190565b50600090565b6001600160a01b0381166000908152600080516020615a00833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615a0083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615ba0833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615960833981519152602052604090205460ff16613a5b576001600160a01b038116600090815260008051602061596083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615ac0833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615a20833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615a2083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615a40833981519152600080516020615920833981519152600080a4600190565b6001600160a01b0381166000908152600080516020615c40833981519152602052604090205460ff16613a5b576001600160a01b0381166000908152600080516020615c4083398151915260205260409020805460ff1916600117905533906001600160a01b0316600080516020615aa0833981519152600080516020615920833981519152600080a4600190565b6000818152600080516020615b40833981519152602090815260408083206001600160a01b038616845290915290205460ff16613d32576000818152600080516020615b40833981519152602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b031690600080516020615920833981519152600080a4600190565b5050600090565b91909182516001600160401b038111611f6f57613d5a81612717845461214b565b6020601f8211600114613d9657819061245c939495600092613d8b5750508160011b916000199060031b1c19161790565b01519050388061273a565b601f19821690613dab84600052602060002090565b9160005b818110613de657509583600195969710613dcd57505050811b019055565b015160001960f88460031b161c19169055388080612786565b9192602060018192868b015181550194019201613daf565b60008051602061598083398151915254600160401b811015611f6f57600181016000805160206159808339815191525560006000805160206159808339815191525482101561243d5760008051602061598083398151915290527f1881c5df5443b563aa79837020da6f3525bbc1de5426f6a8369e84b12b2c1f050155565b600080516020615a8083398151915254600160401b811015611f6f5760018101600080516020615a80833981519152556000600080516020615a808339815191525482101561243d57600080516020615a8083398151915290527f61cb9599a58b4bc1e95f7d63c2591482386071202c54d9ef1ab6c4df8895a4260155565b9493926001600160401b03606093613f27938852166020870152608060408701526080860190610620565b930152565b906001600160401b03613f4683516001600160401b031690565b16156140465781516001600160401b0316916020810192613f708451916040840192835191614ff1565b93613f7a856120a9565b92613f9b613f8f85546001600160401b031690565b6001600160401b031690565b61403557614024817fabe16d0e346dbd6bb822d69ae6eb684c5a85391dac8a689f30b5577cebbcb21495613ff9613fdc61376095516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b614007855160018301613d39565b6002865191015561401788613dfe565b516001600160401b031690565b915192516040519384938885613efc565b630313b28560e01b60005260046000fd5b633d23e4d160e11b60005260046000fd5b6000818152600080516020615b40833981519152602090815260408083206001600160a01b038616845290915290205460ff1615613d32576000818152600080516020615b40833981519152602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b600080a4600190565b3561106e81612339565b903590601e19813603018212156103dd57018035906001600160401b0382116103dd576020019181360383136103dd57565b916141596020926001600160401b039296959660408652604086019161285b565b9416910152565b6001600160401b03614171826140fc565b16156140465760208101906141868282614106565b905015614323576040810135612710811161432357816141e36141c97f6c709e7c783b0ffa2a9da8b3a2bc32ef692f68fac0407a56af322fe370de4240946140fc565b6141dd6141d68785614106565b369161234a565b90614e78565b80946141f9612ec06141f484612107565b615163565b9261422d836000527f89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd011602052604060002090565b90614242613f8f83546001600160401b031690565b1561428b575b5050505061427761425d61145a611455612dfa565b61426686612107565b906001600160e01b03851691615557565b5050604080519182526020820192909252a2565b614317614303846142f461430b956142d16142c77fed457cc56f2f6159a5388260fd7f0309e793291f8c0e089f855f8fd58b6ce36b9988614106565b90600184016126f8565b6142da866140fc565b6001600160401b03166001600160401b0319825416179055565b6142fd87613e7d565b83614106565b9390926140fc565b60405193849384614138565b0390a283388080614248565b63024ef5c960e51b60005260046000fd5b61433c612dfa565b8082036143825750600052600080516020615b208339815191526020526040600020908154156137df57600382015461437157565b630d7b317160e31b60005260046000fd5b90631d56b54b60e31b60005260045260245260446000fd5b6001600160a01b03161561266157565b600080516020615a6083398151915254604051634ce975a360e11b81526004810192909252606090829060249082906001600160a01b03165afa90811561132e57600091614403575b506020015165ffffffffffff1690565b6060813d60601161446c575b8161441c60609383611fe1565b810103126144685781604060209261106e945081519261443b84611f90565b815161444681610a33565b84528482015161445581610a33565b85850152500151604082015291506143f3565b5080fd5b3d915061440f565b919081101561243d576060020190565b3563ffffffff811681036103dd5790565b8054600160401b811015611f6f57610d9191600182018155612a19565b919390949260009260009660009660046144cb86612f87565b01549360005b8281106144e45750505050505050929190565b6144f28184869d9c9d614474565b9760408901359a8b15801561466b575b61465a57878c1061463f5789359060005b8481106146145750614524826120a9565b80546001600160401b03168015614603576145498c916141dd600161454e9501612185565b612e67565b156145f257848d938461456091611f31565b9b6020019e8f9e8f61457190614484565b63ffffffff169061458191613317565b61458a91611f31565b9d61459490614484565b9061459f9185614e46565b6145a891611f31565b9c6145b28861208c565b6145bb90614495565b509182556145c890614484565b60018201906145e6919063ffffffff1663ffffffff19825416179055565b600201556001016144d1565b63435e3df360e11b60005260046000fd5b6307db1be560e41b60005260046000fd5b8261462082898b614474565b351461462e57600101614513565b6376ebe0a360e11b60005260046000fd5b630763c2c360e51b60005260048c9052602488905260446000fd5b633e5fcf1560e21b60005260046000fd5b5063ffffffff61467d60208c01614484565b1615614502565b600080516020615c20833981519152549192916146c36146bd65ffffffffffff60a884901c166001600160a01b03600885901c16615657565b92612f87565b600181015491906147106146df6001600160a01b03851661122b565b60028301546040516370a0823160e01b81526001600160a01b03909116600482015291602090839081906024820190565b0381845afa90811561132e57614738926000926148c4575b5061473290614d41565b90614f10565b600080516020615a608339815191525490929061475d906001600160a01b031661122b565b6040516313520f5760e21b81529590602087600481845afa90811561132e576147946020926147bf996000916148a7575b50615192565b604051635fce2f7360e11b815265ffffffffffff909116600482015297889190829081906024820190565b03915afa92831561132e5761481a61483f95614814614833956148289561480e6148096147ff61483a9b6148459f600091614888575b5060ff8616614732565b9360d81c60ff1690565b614eac565b916157ec565b90611f31565b9060038101549054916157ec565b9360a01c61ffff1690565b61ffff1690565b611f21565b9061577b565b80831161486f5750818111614858575050565b63bb9d933b60e01b60005260045260245260446000fd5b6343aab4a360e11b600052600483905260245260446000fd5b6148a1915060203d602011612e6057612e588183611fe1565b386147f5565b6148be9150843d8611611327576113198183611fe1565b3861478e565b6147329192506148e29060203d602011612e6057612e588183611fe1565b9190614728565b61ffff8116036103dd57565b3561106e816148e9565b600080516020615bc083398151915254600160401b811015611f6f578060016149479201600080516020615bc083398151915255600080516020615bc0833981519152612f6b565b9190916149eb5760a06004918035845560018401614988602083013561496c81610587565b82546001600160a01b0319166001600160a01b03909116178255565b6040820135614996816148e9565b815461ffff918216851b91851b19161790556149da6149b760608301612ae3565b6002860180546001600160a01b0319166001600160a01b03909216919091179055565b608081013560038501550135910155565b612460565b91909160a08060c0830194803584526020810135614a0d81610587565b600180841b0316602085015261ffff6040820135614a2a816148e9565b1660408501526060810135614a3e81610587565b600180841b03166060850152608081013560808501520135910152565b8035612ee081108015614ba6575b614b95576020820190614a8161138261122b84612ae3565b614a9061138260608501612ae3565b60808301358015918215614b82575b5050614b715760a082013515614b6057604082016103e861ffff614ac2836148f5565b1611614b3d57507f4d65ea4765c1c204c4a6882a91a420cb6f1d9fec39f5a6d40e5ebf591c2c056491614afd6113d561122b61376094612ae3565b50614b2f600080516020615bc083398151915254614b1a836148ff565b80611447576001600160e01b0316600061542b565b5050604051918291826149f0565b614b49611bb7916148f5565b6389cb95e960e01b60005261ffff16600452602490565b637f349ee160e11b60005260046000fd5b633fe89cb960e11b60005260046000fd5b614b8d919250613306565b103880614a9f565b63197f247760e01b60005260046000fd5b5061c3508111614a69565b60407f9026541b5a8b912fcc577e1e5d095b812c9d8de7fefbc0280e791126a25e60ac91614bde8161439a565b60008051602061590083398151915280546001600160a01b039283166001600160a01b0319821681179092558351921682526020820152a1565b614c218161439a565b6001600160a01b03811690614c3582615881565b15614c87577f9af05cf8274349906c4818da137d738fd8d36d3b092ceb12e30ce8f0d754974f918160ff614c73614c6d602095614d41565b9261292f565b911660ff19825416179055604051908152a1565b63da562e7d60e01b60005260046000fd5b65ffffffffffff811615614d2057600080516020615c20833981519152805465ffffffffffff60a81b60a884811b9190911665ffffffffffff60a81b198316179092556040805165ffffffffffff9290931c82168352921660208201527f9b9450d02e5838e5d70dfc180234b518f6f6b6c0793775ccd00f87f4d639751d9181908101613760565b63410508c760e01b60005260046000fd5b614d396151af565b6123046151af565b60405163313ce56760e01b81529190602090839060049082906001600160a01b03165afa91821561132e57600092614d98575b5060ff821660128111614d845750565b63fd91cbed60e01b60005260045260246000fd5b614db291925060203d6020116139ba576139ab8183611fe1565b9038614d74565b60001981019190821161041e57565b9190820391821161041e57565b6000526000805160206159c0833981519152602052604060002054151590565b929091906000915b8451831015614e3e57604060019160009060208660051b8901015190818110600014614e32578252602052205b920191614dfd565b90825260205220614e2a565b915092501490565b91614e5d9063ffffffff64496cebb8009316613317565b614e688282856157ec565b92091515810180911161041e5790565b90614ea66133fc916040519283916001600160401b0360208401961686526040808401526060830190610620565b51902090565b60ff16604d811161041e57600a0a90565b9060ff1680601214612fde5780601210614ef15760120360ff811161041e5761106e91614eeb600192614eac565b906153a0565b601119019060ff821161041e57614f0a61106e92614eac565b90613317565b9060ff1660128114612fde5760128110614f3f576011190160ff811161041e5761106e91614eeb600092614eac565b6012039060ff821161041e57614f0a61106e92614eac565b6040516323b872dd60e01b60208083019182526001600160a01b0394851660248401529490931660448201526064808201959095529384529260009190614f9f608482611fe1565b519082855af115612923576000513d614fe857506001600160a01b0381163b155b614fc75750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415614fc0565b9161502191614ea6916040519384926001600160401b036020850197168752606060408501526080840190610620565b90606083015203601f198101835282611fe1565b8054801561505e57600019019061504c828261280a565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b60008181526000805160206159c08339815191526020526040902054908115613d325760001982019082821161041e57600080516020615b008339815191525460001981019390841161041e578383600095615108950361510e575b5050506150ea600080516020615b00833981519152615035565b6000805160206159c083398151915290600052602052604060002090565b55600190565b6150ea6151549161513d61513361515a95600080516020615b0083398151915261280a565b90549060031b1c90565b928391600080516020615b0083398151915261280a565b90612442565b553880806150d0565b80549081615172575050600090565b8160001981011161041e5760005260001990602060002001015460201c90565b65ffffffffffff6000199116019065ffffffffffff821161041e57565b60ff600080516020615c008339815191525460401c16156151cc57565b631afcd79f60e31b60005260046000fd5b600181111561106e57806001600160801b8210156152fe575b6152a461529a61529061528661527c6152726152616152ab9760046152b09a600160401b8110156152f1575b6401000000008110156152e4575b620100008110156152d7575b6101008110156152ca575b60108110156152bd575b10156152b5575b60030260011c90565b61526b818b612697565b0160011c90565b61526b818a612697565b61526b8189612697565b61526b8188612697565b61526b8187612697565b61526b8186612697565b8093612697565b821190565b900390565b60011b615258565b60041c9160021b91615251565b60081c9160041b91615247565b60101c9160081b9161523c565b60201c9160101b91615230565b60401c9160201b91615222565b50506152b06152ab6152a461529a61529061528661527c6152726152616153258a60801c90565b9850600160401b97506151f69650505050505050565b91905b83821061534b5750505090565b9091928083169080841860011c820180921161041e578460005263ffffffff82602060002001541663ffffffff84161060001461538c5750925b919061533e565b9392506001810180911161041e5791615385565b906001806153af8382866157ec565b946153b981610609565b161491826153d2575b50501515810180911161041e5790565b90809250156126a15760019009151538806153c2565b8054600160401b811015611f6f576154059160018201815561280a565b6149eb57815160209283015190921b63ffffffff191663ffffffff909216919091179055565b6000805160206159a083398151915254919291801561552d5761545061548791614db9565b6000805160206159a08339815191526000527f2060c037175d92fda9c6bae663cfb46d241cf6f66cac38481ca19c403ebfb7920190565b9081546154a161549a8263ffffffff1690565b9160201c90565b9263ffffffff80841692169180831161551c578692036154db576154d792509063ffffffff82549181199060201b169116179055565b9190565b50506154d7906154f86154ec612012565b63ffffffff9092168252565b6001600160e01b03851660208201525b6000805160206159a08339815191526153e8565b632520601d60e01b60005260046000fd5b506155519061553d6154ec612012565b6001600160e01b0384166020820152615508565b60009190565b805492939280156155ec5761556e61557b91614db9565b8260005260206000200190565b8054602081901c9363ffffffff9182169291811680841161551c578793036155ba57506154d792509063ffffffff82549181199060201b169116179055565b9150506154d7916155d86155cc612012565b63ffffffff9093168352565b6001600160e01b03861660208301526153e8565b5090615551916155fd6155cc612012565b6001600160e01b03851660208301526153e8565b51906001600160501b03821682036103dd57565b908160a09103126103dd5761563981615611565b9160208201519160408101519161106e608060608401519301615611565b604051633fabe5a360e21b8152919060a090839060049082906001600160a01b03165afa91821561132e576000928380928192615740575b50600085131561572a578215615719576001600160501b0381166001600160501b038316106156f65750506156c48142614dc8565b65ffffffffffff8316106156d757505090565b6385ada3f360e01b60005260045265ffffffffffff1660245260446000fd5b630cb58a9360e31b6000526001600160501b039081166004521660245260446000fd5b63b3e6505f60e01b60005260046000fd5b633c30523f60e01b600052600485905260246000fd5b9250505061576791925060a03d60a011615774575b61575f8183611fe1565b810190615625565b929493909291503861568f565b503d615755565b80820290600019838209908280831092039180830392146157e1578161271011156157da577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9193612710910990828211900360fc1b910360041c170290565b60116158ee565b506127109250500490565b91818302916000198185099383808610950394808603951461587457848311156158675790829109816000038216809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b60116003841502186158ee565b50509061106e9250612697565b806000526000805160206159c083398151915260205260406000205415600014613a5b576158bd81600080516020615b00833981519152612822565b600080516020615b0083398151915254906000526000805160206159c0833981519152602052604060002055600190565b634e487b716000526020526024601cfdfe89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0012f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd004fb3f6e6e654f6130d3f2fa1f8ac1a8341f2fb9e0730e1425ef2cfee0612ce99389fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00e89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00a89fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00889fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd005b16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c263f10a9fca1980f9ac4a56a776ebe74bab62acb2d47edad7c1e0e938757dc0768bf109b95a5c15fb2bb99041323c27d15f8675e11bf7420a1cd6ad64c394f4689fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd010b92d52e77ebaa0cae5c23e882d85609efbcb44029214147dd132daf9ef1018af850d585eb7f024ccee5e68e55f2c26cc72e1e6ee456acf62135757a5eb9d4a1089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00389fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00789fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00b02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd0149b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177589fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd00989fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd002f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0089fd6609332cbe19e528bcd8d4a7f5648af9fc2ad8e8f65d6e02fc4dfabfd013985e7e44dfcb208cb67a8ab5f4ddea68569700462a8bdd41960667c1dc173537a26469706673582212202f5793a768ff3c128ced0a1dd18aaa8ba198242d40cf3efbc94116561556dc7464736f6c634300081c0033","name":"CoverOrderAllocator","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":false,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.20;\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 *\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 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\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 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    // 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 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    // 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 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    // 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 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"},{"file_path":"@openzeppelin/contracts/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"contracts/core/interfaces/IAggregatorV3.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title IAggregatorV3\n * @dev Chainlink Aggregator V3 interface for price feeds. Mirrors\n *      https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\n */\ninterface IAggregatorV3 {\n    /**\n     * @notice Number of decimals for the price value.\n     * @return The decimals.\n     */\n    function decimals() external view returns (uint8);\n\n    /**\n     * @notice Human-readable asset pair description (e.g., \"ETH/USD\").\n     * @return The asset pair description.\n     */\n    function description() external view returns (string memory);\n\n    /**\n     * @notice Contract version.\n     * @return Version as a uint256 value.\n     */\n    function version() external view returns (uint256);\n\n    /**\n     * @notice Obtain round data. Used for historical information, each round corresponds to a data point.\n     * @dev Implementations that do not retain historical rounds (e.g. live FTSO-backed\n     *      aggregators) should revert with a `NotImplemented()` custom error.\n     */\n    function getRoundData(uint80 _roundId)\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n\n    /**\n     * @notice Fetch the latest round information. Retrieves the last recorded data.\n     */\n    function latestRoundData()\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n}\n\n"},{"file_path":"contracts/core/lib/PriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {IAggregatorV3} from \"../interfaces/IAggregatorV3.sol\";\n\n/**\n * @title PriceFeed\n * @notice Reads and validates a Chainlink-compatible price feed answer.\n * @custom:security-contact securityreport@firelight.finance\n */\nlibrary PriceFeed {\n    /// @notice Thrown when the feed returns a non-positive answer.\n    /// @param price The non-positive answer returned by the feed.\n    error InvalidAssetPrice(int256 price);\n    /// @notice Thrown when the feed reports a zero `updatedAt` timestamp.\n    error InvalidAssetPriceUpdatedAt();\n    /// @notice Thrown when the feed answer is older than the allowed maximum age.\n    /// @param updatedAt Timestamp of the feed answer.\n    /// @param maxPriceAge Maximum tolerated age, in seconds.\n    error PriceFeedTooOld(uint256 updatedAt, uint48 maxPriceAge);\n    /// @notice Thrown when the answered round is older than the requested round.\n    /// @param roundId Round id of the latest answer.\n    /// @param answeredInRound Round in which the answer was computed.\n    error StaleAssetPriceRound(uint80 roundId, uint80 answeredInRound);\n\n    /// @notice Reads `latestRoundData` and validates positivity, round, and freshness.\n    /// @param feedAdapter Chainlink-compatible feed to query.\n    /// @param maxAge Maximum tolerated age of the answer, in seconds.\n    /// @return price The validated price, in the feed's own decimals.\n    function getPrice(\n        IAggregatorV3 feedAdapter,\n        uint48 maxAge\n    ) internal view returns (uint256 price) {\n        (uint80 roundId, int256 answer,, uint256 updatedAt, uint80 answeredInRound) = feedAdapter.latestRoundData();\n\n        if (answer <= 0) revert InvalidAssetPrice(answer);\n        if (updatedAt == 0) revert InvalidAssetPriceUpdatedAt();\n        if (answeredInRound < roundId) revert StaleAssetPriceRound(roundId, answeredInRound);\n        if (block.timestamp - updatedAt > maxAge) revert PriceFeedTooOld(updatedAt, maxAge);\n\n        return (uint256(answer));\n    }\n}\n"},{"file_path":"contracts/core/lib/Decimals.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n/**\n * @title Decimals\n * @notice Converts a fixed-point amount between two decimal scales.\n * @custom:security-contact securityreport@firelight.finance\n */\nlibrary Decimals {\n    /// @notice Rescales `amount` from `fromDecimals` to `toDecimals`.\n    /// @dev Scaling up is exact (rounding is irrelevant); scaling down applies `rounding`.\n    /// @param amount Amount expressed with `fromDecimals` decimals.\n    /// @param fromDecimals Decimals the amount is currently expressed in.\n    /// @param toDecimals Target decimals.\n    /// @param rounding Rounding direction used when scaling down.\n    /// @return The amount expressed with `toDecimals` decimals.\n    function convert(\n        uint256 amount,\n        uint8 fromDecimals,\n        uint8 toDecimals,\n        Math.Rounding rounding\n    ) internal pure returns (uint256) {\n        if (fromDecimals == toDecimals) return amount;\n        if (fromDecimals < toDecimals) {\n            return amount * 10 ** (toDecimals - fromDecimals);\n        }\n        return Math.mulDiv(amount, 1, 10 ** (fromDecimals - toDecimals), rounding);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721Receiver} from \"../IERC721Receiver.sol\";\nimport {IERC721Errors} from \"../../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Library that provide common ERC-721 utility functions.\n *\n * See https://eips.ethereum.org/EIPS/eip-721[ERC-721].\n *\n * _Available since v5.1._\n */\nlibrary ERC721Utils {\n    /**\n     * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}\n     * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\n     *\n     * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\n     * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept\n     * the transfer.\n     */\n    function checkOnERC721Received(\n        address operator,\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal {\n        if (to.code.length > 0) {\n            try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) {\n                    // Token rejected\n                    revert IERC721Errors.ERC721InvalidReceiver(to);\n                }\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    // non-IERC721Receiver implementer\n                    revert IERC721Errors.ERC721InvalidReceiver(to);\n                } else {\n                    assembly (\"memory-safe\") {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)\n\npragma solidity ^0.8.20;\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 signaling 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"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @title ERC-721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC-721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n     * reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC721/IERC721.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC-721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/SafeCast.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            // bubble errors\n            if iszero(success) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/utils/structs/Checkpoints.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/Checkpoints.sol)\n// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"../math/Math.sol\";\n\n/**\n * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in\n * time, and later looking up past values by block number. See {Votes} as an example.\n *\n * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new\n * checkpoint for the current transaction block using the {push} function.\n */\nlibrary Checkpoints {\n    /**\n     * @dev A value was attempted to be inserted on a past checkpoint.\n     */\n    error CheckpointUnorderedInsertion();\n\n    struct Trace224 {\n        Checkpoint224[] _checkpoints;\n    }\n\n    struct Checkpoint224 {\n        uint32 _key;\n        uint224 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the\n     * library.\n     */\n    function push(\n        Trace224 storage self,\n        uint32 key,\n        uint224 value\n    ) internal returns (uint224 oldValue, uint224 newValue) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace224 storage self) internal view returns (uint224) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace224 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(\n        Checkpoint224[] storage self,\n        uint32 key,\n        uint224 value\n    ) private returns (uint224 oldValue, uint224 newValue) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            Checkpoint224 storage last = _unsafeAccess(self, pos - 1);\n            uint32 lastKey = last._key;\n            uint224 lastValue = last._value;\n\n            // Checkpoint keys must be non-decreasing.\n            if (lastKey > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (lastKey == key) {\n                last._value = value;\n            } else {\n                self.push(Checkpoint224({_key: key, _value: value}));\n            }\n            return (lastValue, value);\n        } else {\n            self.push(Checkpoint224({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint224[] storage self,\n        uint32 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint224[] storage self,\n        uint32 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint224[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint224 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n\n    struct Trace208 {\n        Checkpoint208[] _checkpoints;\n    }\n\n    struct Checkpoint208 {\n        uint48 _key;\n        uint208 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace208 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the\n     * library.\n     */\n    function push(\n        Trace208 storage self,\n        uint48 key,\n        uint208 value\n    ) internal returns (uint208 oldValue, uint208 newValue) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace208 storage self) internal view returns (uint208) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace208 storage self) internal view returns (bool exists, uint48 _key, uint208 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace208 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(\n        Checkpoint208[] storage self,\n        uint48 key,\n        uint208 value\n    ) private returns (uint208 oldValue, uint208 newValue) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            Checkpoint208 storage last = _unsafeAccess(self, pos - 1);\n            uint48 lastKey = last._key;\n            uint208 lastValue = last._value;\n\n            // Checkpoint keys must be non-decreasing.\n            if (lastKey > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (lastKey == key) {\n                last._value = value;\n            } else {\n                self.push(Checkpoint208({_key: key, _value: value}));\n            }\n            return (lastValue, value);\n        } else {\n            self.push(Checkpoint208({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint208[] storage self,\n        uint48 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint208[] storage self,\n        uint48 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint208[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint208 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n\n    struct Trace160 {\n        Checkpoint160[] _checkpoints;\n    }\n\n    struct Checkpoint160 {\n        uint96 _key;\n        uint160 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the\n     * library.\n     */\n    function push(\n        Trace160 storage self,\n        uint96 key,\n        uint160 value\n    ) internal returns (uint160 oldValue, uint160 newValue) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace160 storage self) internal view returns (uint160) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace160 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(\n        Checkpoint160[] storage self,\n        uint96 key,\n        uint160 value\n    ) private returns (uint160 oldValue, uint160 newValue) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            Checkpoint160 storage last = _unsafeAccess(self, pos - 1);\n            uint96 lastKey = last._key;\n            uint160 lastValue = last._value;\n\n            // Checkpoint keys must be non-decreasing.\n            if (lastKey > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (lastKey == key) {\n                last._value = value;\n            } else {\n                self.push(Checkpoint160({_key: key, _value: value}));\n            }\n            return (lastValue, value);\n        } else {\n            self.push(Checkpoint160({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint160[] storage self,\n        uint96 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint160[] storage self,\n        uint96 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint160[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint160 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SafeCast} from \"./math/SafeCast.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    using SafeCast for *;\n\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev The string being parsed contains characters that are not in scope of the given base.\n     */\n    error StringsInvalidChar();\n\n    /**\n     * @dev The string being parsed is not a properly formatted address.\n     */\n    error StringsInvalidAddressFormat();\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            assembly (\"memory-safe\") {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                assembly (\"memory-safe\") {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\n     * representation, according to EIP-55.\n     */\n    function toChecksumHexString(address addr) internal pure returns (string memory) {\n        bytes memory buffer = bytes(toHexString(addr));\n\n        // hash the hex part of buffer (skip length + 2 bytes, length 40)\n        uint256 hashValue;\n        assembly (\"memory-safe\") {\n            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\n        }\n\n        for (uint256 i = 41; i > 1; --i) {\n            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\n            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\n                // case shift by xoring with 0x20\n                buffer[i] ^= 0x20;\n            }\n            hashValue >>= 4;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input) internal pure returns (uint256) {\n        return parseUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        uint256 result = 0;\n        for (uint256 i = begin; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 9) return (false, 0);\n            result *= 10;\n            result += chr;\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `int256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input) internal pure returns (int256) {\n        return parseInt(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\n        (bool success, int256 value) = tryParseInt(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\n     * the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\n        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    uint256 private constant ABS_MIN_INT256 = 2 ** 255;\n\n    /**\n     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character or if the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, int256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseIntUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseIntUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, int256 value) {\n        bytes memory buffer = bytes(input);\n\n        // Check presence of a negative sign.\n        bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        bool positiveSign = sign == bytes1(\"+\");\n        bool negativeSign = sign == bytes1(\"-\");\n        uint256 offset = (positiveSign || negativeSign).toUint();\n\n        (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\n\n        if (absSuccess && absValue < ABS_MIN_INT256) {\n            return (true, negativeSign ? -int256(absValue) : int256(absValue));\n        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\n            return (true, type(int256).min);\n        } else return (false, 0);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input) internal pure returns (uint256) {\n        return parseHexUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseHexUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\n     * invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseHexUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseHexUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        // skip 0x prefix if present\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 offset = hasPrefix.toUint() * 2;\n\n        uint256 result = 0;\n        for (uint256 i = begin + offset; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 15) return (false, 0);\n            result *= 16;\n            unchecked {\n                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\n                // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.\n                result += chr;\n            }\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as an `address`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input) internal pure returns (address) {\n        return parseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\n        (bool success, address value) = tryParseAddress(input, begin, end);\n        if (!success) revert StringsInvalidAddressFormat();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\n     * formatted address. See {parseAddress} requirements.\n     */\n    function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\n        return tryParseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\n     * formatted address. See {parseAddress} requirements.\n     */\n    function tryParseAddress(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, address value) {\n        if (end > bytes(input).length || begin > end) return (false, address(0));\n\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\n\n        // check that input is the correct length\n        if (end - begin == expectedLength) {\n            // length guarantees that this does not overflow, and value is at most type(uint160).max\n            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\n            return (s, address(uint160(v)));\n        } else {\n            return (false, address(0));\n        }\n    }\n\n    function _tryParseChr(bytes1 chr) private pure returns (uint8) {\n        uint8 value = uint8(chr);\n\n        // Try to parse `chr`:\n        // - Case 1: [0-9]\n        // - Case 2: [a-f]\n        // - Case 3: [A-F]\n        // - otherwise not supported\n        unchecked {\n            if (value > 47 && value < 58) value -= 48;\n            else if (value > 96 && value < 103) value -= 87;\n            else if (value > 64 && value < 71) value -= 55;\n            else return type(uint8).max;\n        }\n\n        return value;\n    }\n\n    /**\n     * @dev Reads a bytes32 from a bytes array without bounds checking.\n     *\n     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n     * assembly block as such would prevent some optimizations.\n     */\n    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\n        // This is not memory safe in the general case, but all calls to this private function are within bounds.\n        assembly (\"memory-safe\") {\n            value := mload(add(buffer, add(0x20, offset)))\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/Hashes.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library of standard hash functions.\n *\n * _Available since v5.1._\n */\nlibrary Hashes {\n    /**\n     * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.\n     *\n     * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n     */\n    function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {\n        return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a);\n    }\n\n    /**\n     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.\n     */\n    function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, a)\n            mstore(0x20, b)\n            value := keccak256(0x00, 0x40)\n        }\n    }\n}\n"},{"file_path":"contracts/core/interfaces/ICoverOrderAllocator.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IFirelightVault} from \"./IFirelightVault.sol\";\nimport {IAggregatorV3} from \"./IAggregatorV3.sol\";\nimport {CoverNFT} from \"../CoverNFT.sol\";\n\n/**\n * @title ICoverOrderAllocator\n * @notice Cover order lifecycle, off-chain matching commit/settle, capacity, and\n *         protocol-concentration configuration for the Firelight cover market.\n *\n * ## Decimal convention\n *\n * All on-chain monetary values (cover amounts, premiums, capacity, allocations,\n * protocolConcentration caps × capacity, etc.) are expressed in a **canonical USD unit** with\n * `CANONICAL_DECIMALS` decimals (currently 18), regardless of the underlying premium /\n * first-loss-buffer / vault-asset token decimals. Throughout this interface, \"canonical USD\"\n * always means `CANONICAL_DECIMALS`-decimal USD. Conversion to/from native token decimals\n * happens only at the boundaries:\n *\n *   - Off-chain: callers MUST normalize inputs (e.g. `MarketAllocationInput.coverAmount`,\n *     merkle leaf `allocatedCover`, `commitAllocation` totalAllocated)\n *     from native decimals to canonical decimals before submitting.\n *   - On-chain transfers: premium `safeTransferFrom`, first-loss-buffer transfer, and\n *     `vault.payout()` are denormalized from canonical decimals back to each token's native\n *     decimals at the transfer call site.\n *\n * Supported tokens must implement `decimals() <= CANONICAL_DECIMALS` (validated on registration).\n *\n * ## Off-chain matching flow\n *\n * The matching algorithm runs off-chain (TypeScript engine). The on-chain contract\n * only validates and applies results via a Merkle commit + settle pattern:\n *\n *   1. Read all PENDING orders for the target period via `getCoverOrdersIdByPeriod(period)`\n *   2. For each orderId, read `getCoverOrder(orderId)` and `getCoverOrderMarkets(orderId)`\n *   3. Read protocolConcentration caps via `getSupportedProtocolConcentrationHashes()` + `getEffectiveProtocolConcentration(hash)\n *   4. Compute capacity: `(config.firstLossBufferToken.balanceOf(config.firstLossBuffer)\n *      + vault.totalAssets() * assetPriceUSD / 10**priceFeedDecimals) * config.effectiveLeverage / config.minCAR`\n *   5. Run the matching algorithm → produces per-order `allocatedCoverPerMarket[]`\n *   6. Build a StandardMerkleTree with leaves: `(uint256 orderId, (bytes32,uint256)[] marketCoverAllocations)`\n *      (premiums are recomputed on-chain at settlement, pro-rata from each order's stored terms)\n *   7. Call `commitAllocation(commitmentPeriod, merkleRoot, totalAllocated, matchingCapacity)`\n *      to commit, where `matchingCapacity` is the capacity of step 4 the matching ran against\n *   8. Call `batchSettleCoverOrder(params)` or `settleCoverOrder(...)` for each order with its Merkle proof\n *\n * ## Leaf encoding\n *\n * Double-hash per OpenZeppelin standard:\n *   `keccak256(bytes.concat(keccak256(abi.encode(orderId, marketCoverAllocations))))`\n *\n * ## ProtocolConcentration cap\n *\n * A market belongs to a protocolConcentration group identified by\n *   `protocolConcentrationHash = keccak256(abi.encode(chainId, protocol))`\n * Multiple markets sharing the same (chainId, protocol) share a single cap. During\n * settlement, cumulative cover per protocolConcentration group must not exceed:\n *   `protocolConcentrationBps * totalAvailableCapacity / 10000`\n *\n * ProtocolConcentration caps are governed independently from market registration. A market\n * whose protocolConcentration has no cap configured is effectively disabled.\n */\ninterface ICoverOrderAllocator {\n    // --- Enums ---\n\n    /// @notice Whether a cover order is a new purchase or a renewal of existing cover.\n    enum CoverOrderType {\n        NEW,\n        RENEWAL\n    }\n\n    /// @notice Lifecycle status of a cover order.\n    enum CoverOrderStatus {\n        PENDING,\n        /// Fully settled: allocated cover equals the requested amount.\n        MATCHED,\n        /// Settled with allocated cover below the requested amount.\n        PARTIAL,\n        CANCELLED\n    }\n\n    // --- Structs ---\n\n    /// @notice A protected market on a specific chain and protocol.\n    struct Market {\n        uint64 chainId;\n        string protocol;\n        /// Protocol-specific market identifier.\n        bytes32 market;\n    }\n\n    /// @notice Input to set a (protocol, chainId) concentration group's cap.\n    struct ProtocolConcentrationInput {\n        uint64 chainId;\n        string protocol;\n        /// Maximum share of capacity the group may take, in bps.\n        uint256 maxProtocolConcentrationBps;\n    }\n\n    /// @notice The (protocol, chainId) tuple a concentration hash was derived from.\n    struct ProtocolConcentration {\n        uint64 chainId;\n        string protocol;\n    }\n\n    /// @notice Initialization parameters for the allocator.\n    struct InitParams {\n        IFirelightVault vault;\n        address premiumCollector;\n        CoverNFT coverNFT;\n        IAggregatorV3 priceFeedAdapter;\n        /// Maximum tolerated price age, in seconds.\n        uint48 maxPriceAge;\n        address[] premiumTokens;\n        /// Receives DEFAULT_ADMIN_ROLE.\n        address admin;\n        /// Receives ADMIN_ROLE.\n        address adminRole;\n        address curatorRole;\n        address allocatorRole;\n        address configAdminRole;\n        ProtocolConcentrationInput[] initialProtocolConcentrations;\n        Market[] newMarkets;\n        /// Initial capacity configuration (effective from period 0).\n        CapacityConfig capacityConfig;\n    }\n\n    /// @notice Per-market cover request submitted when creating an order.\n    struct MarketAllocationInput {\n        bytes32 marketId;\n        /// Annual cover rate, in bps.\n        uint32 coverRateAnnual;\n        /// Requested cover in canonical USD, pre-normalized by the caller\n        /// (e.g. `nativeAmount * 10**(CANONICAL_DECIMALS - premiumTokenDecimals)`).\n        uint256 coverAmount;\n    }\n\n    /// @notice Per-market allocation stored for an order (request + settled result).\n    struct MarketAllocation {\n        bytes32 marketId;\n        /// Annual cover rate, in bps.\n        uint32 coverRateAnnual;\n        /// Requested cover, in canonical USD.\n        uint256 coverAmount;\n        /// Cover actually allocated on settle, in canonical USD.\n        uint256 allocatedCoverAmount;\n    }\n\n    /// @notice Full cover order record.\n    struct CoverOrder {\n        // Slot: buyer (20) + orderType (1) + status (1).\n        address buyer;\n        CoverOrderType orderType;\n        CoverOrderStatus status;\n        address payoutRecipient;\n        /// Off-chain beneficiary reference.\n        string beneficiaryAddress;\n        address premiumToken;\n        /// Total requested cover across markets, in canonical USD.\n        uint256 totalCoverAmount;\n        /// Total premium owed, in canonical USD.\n        uint256 totalPremiumAmount;\n        /// Cover-amount-weighted average annual rate, in bps.\n        uint256 weightedAvgRate;\n        /// Total cover allocated on settle, in canonical USD.\n        uint256 allocatedCoverAmount;\n        /// Premium charged for the allocated cover, in canonical USD.\n        uint256 allocatedPremiumAmount;\n        /// Target period the order is matched and settled in.\n        uint256 period;\n    }\n\n    /// @notice Per-period capacity configuration (checkpointed; effective at currentPeriod() + 1).\n    struct CapacityConfig {\n        /// Minimum capital adequacy ratio, in bps (1.2x to 5x, inclusive).\n        uint256 minCAR;\n        /// ERC20 (decimals ≤ CANONICAL_DECIMALS) used as first-loss-buffer collateral.\n        IERC20 firstLossBufferToken;\n        /// Upper margin (bps) tolerated between the submitted `totalAllocated` and the recomputed\n        /// capacity at commit/recommit, to absorb price/FLB drift. 0 = strict (legacy behavior).\n        uint16 divergenceToleranceBps;\n        /// Custody wallet holding the first-loss-buffer balance.\n        address firstLossBuffer;\n        /// Leverage applied to collateral when computing capacity, in bps\n        /// (> 0, <= MAX_LEVERAGE_FACTOR * minCAR).\n        uint256 effectiveLeverage;\n        /// Minimum per-market cover amount allowed on an order, in canonical USD.\n        uint256 minOrderMarketCoverAmount;\n    }\n\n    /// @notice Committed off-chain matching results and settlement accounting for a period.\n    struct AllocationCommitment {\n        /// Root of the StandardMerkleTree of settlement leaves.\n        bytes32 root;\n        /// Effective period capacity (tolerance included), in canonical USD.\n        uint256 totalAvailableCapacity;\n        /// Declared sum of allocated cover across the tree, in canonical USD.\n        uint256 totalDeclaredAllocated;\n        /// Cumulative cover settled so far, in canonical USD.\n        uint256 totalSettledCover;\n        /// Cumulative premium settled so far, in canonical USD.\n        uint256 totalSettledPremium;\n        /// Timestamp at which the grace elapses and settlement can begin. Frozen at\n        /// commit/recommit time from the then-current `settlementGracePeriod`; later\n        /// grace updates never alter an already-published window.\n        uint48 graceExpiresAt;\n    }\n\n    /// @notice Per-market allocation encoded in a settlement leaf and passed to settle.\n    struct MarketCoverAllocation {\n        bytes32 marketId;\n        /// Allocated cover for the market, in canonical USD.\n        uint256 allocatedCover;\n    }\n\n    /// @notice Parameters to settle a single order in a batch.\n    struct SettleParams {\n        uint256 orderId;\n        MarketCoverAllocation[] marketCoverAllocations;\n        /// Merkle proof of the order's leaf against the period commitment root.\n        bytes32[] proof;\n    }\n\n    // --- Events ---\n\n    /**\n     * @notice Emitted when a cover order is created for the next period.\n     * @param coverOrderId New cover order id.\n     * @param buyer Account that pays the premium.\n     * @param payoutRecipient Account that receives the payout if a covered incident occurs.\n     * @param beneficiaryAddress Off-chain beneficiary reference recorded with the order.\n     * @param premiumToken ERC20 used to pay the premium.\n     * @param totalCoverAmount Total requested cover across markets, in canonical USD.\n     * @param totalPremiumAmount Total premium owed for the order, in canonical USD.\n     * @param weightedAvgRate Cover-amount-weighted average annual rate, in bps.\n     * @param orderType Whether the order is NEW or a RENEWAL.\n     * @param period Target period the order will be matched and settled in.\n     */\n    event CoverOrderCreated(\n        uint256 coverOrderId,\n        address buyer,\n        address payoutRecipient,\n        string beneficiaryAddress,\n        address premiumToken,\n        uint256 totalCoverAmount,\n        uint256 totalPremiumAmount,\n        uint256 weightedAvgRate,\n        CoverOrderType orderType,\n        uint256 period\n    );\n\n    /**\n     * @notice Emitted when an order is settled against the committed Merkle root.\n     * @param coverOrderId Settled cover order id.\n     * @param status Resulting status (MATCHED or PARTIAL).\n     * @param allocatedCoverAmount Total cover allocated to the order, in canonical USD.\n     * @param allocatedPremiumAmount Premium charged for the allocated cover, in canonical USD.\n     */\n    event CoverOrderSettled(\n        uint256 coverOrderId,\n        CoverOrderStatus status,\n        uint256 allocatedCoverAmount,\n        uint256 allocatedPremiumAmount\n    );\n\n    /**\n     * @notice Emitted when a pending order is cancelled.\n     * @param coverOrderId Cancelled cover order id.\n     */\n    event CoverOrderCancelled(uint256 coverOrderId);\n\n    /**\n     * @notice Emitted on each commit or recommit of a period's matching results.\n     * @param period Period the commitment applies to.\n     * @param merkleRoot Root of the StandardMerkleTree of settlement leaves.\n     * @param totalAvailableCapacity Effective period capacity (tolerance included), in canonical USD.\n     * @param totalAllocated Declared sum of allocated cover across the tree, in canonical USD.\n     */\n    event AllocationCommitted(\n        uint256 indexed period,\n        bytes32 merkleRoot,\n        uint256 totalAvailableCapacity,\n        uint256 totalAllocated\n    );\n\n    /**\n     * @notice Emitted when a period's allocation commitment is cancelled before any settlement.\n     * @param period Period whose commitment was cancelled.\n     * @param merkleRoot Root of the cancelled commitment.\n     */\n    event AllocationCommitmentCancelled(uint256 indexed period, bytes32 merkleRoot);\n\n    /**\n     * @notice Emitted when the premium collector address changes.\n     * @param oldCollector Previous premium collector.\n     * @param newCollector New premium collector.\n     */\n    event PremiumCollectorUpdated(address oldCollector, address newCollector);\n\n    /**\n     * @notice Emitted when a market is registered.\n     * @param marketId Derived market id.\n     * @param chainId Chain the market lives on.\n     * @param protocol Protocol name the market belongs to.\n     * @param market Protocol-specific market identifier.\n     */\n    event MarketAdded(bytes32 marketId, uint64 chainId, string protocol, bytes32 market);\n\n    /**\n     * @notice Emitted the first time a (protocol, chainId) concentration group is seen.\n     * @param protocolConcentrationHash Hash identifying the concentration group.\n     * @param protocol Protocol name of the group.\n     * @param chainId Chain id of the group.\n     */\n    event ProtocolConcentrationRegistered(bytes32 indexed protocolConcentrationHash, string protocol, uint64 chainId);\n\n    /**\n     * @notice Emitted when a concentration group's cap is set or updated.\n     * @param protocolConcentrationHash Hash identifying the concentration group.\n     * @param oldShareBps Previous cap, in bps.\n     * @param newShareBps New cap, in bps, effective at currentPeriod() + 1.\n     */\n    event ProtocolConcentrationUpdated(\n        bytes32 indexed protocolConcentrationHash,\n        uint256 oldShareBps,\n        uint256 newShareBps\n    );\n\n    /**\n     * @notice Emitted when a premium token is whitelisted.\n     * @param token Added premium token.\n     */\n    event PremiumTokenAdded(address token);\n\n    /**\n     * @notice Emitted when a premium token is removed from the whitelist.\n     * @param token Removed premium token.\n     */\n    event PremiumTokenRemoved(address token);\n\n    /**\n     * @notice Emitted when a new capacity configuration checkpoint is pushed.\n     * @param config The capacity configuration that becomes effective (currentPeriod() + 1, or 0 for the first one).\n     */\n    event CapacityConfigUpdated(CapacityConfig config);\n\n    /**\n     * @notice Emitted when the price feed adapter is replaced.\n     * @param oldPriceFeedAdapter Previous adapter.\n     * @param oldPriceFeedDecimals Previous adapter decimals.\n     * @param newPriceFeedAdapter New adapter.\n     * @param newPriceFeedDecimals New adapter decimals.\n     */\n    event PriceFeedUpdated(\n        address oldPriceFeedAdapter,\n        uint8 oldPriceFeedDecimals,\n        address newPriceFeedAdapter,\n        uint8 newPriceFeedDecimals\n    );\n\n    /**\n     * @notice Emitted when the maximum tolerated price age changes.\n     * @param oldMaxPriceAge Previous max age, in seconds.\n     * @param newMaxPriceAge New max age, in seconds.\n     */\n    event MaxPriceAgeUpdated(uint48 oldMaxPriceAge, uint48 newMaxPriceAge);\n\n    /**\n     * @notice Emitted when the settlement grace period changes.\n     * @param oldGracePeriod Previous grace period, in seconds.\n     * @param newGracePeriod New grace period, in seconds.\n     */\n    event SettlementGracePeriodUpdated(uint48 oldGracePeriod, uint48 newGracePeriod);\n\n    // --- Errors ---\n\n    // -- order creation / market configuration --\n    /// @notice Thrown when an order is created with no markets.\n    error InvalidMarketsLength();\n    /// @notice Thrown when a market entry has a zero cover amount or zero rate.\n    error InvalidMarketsZeroValue();\n    /// @notice Thrown when an order lists the same market more than once.\n    error DuplicateMarket();\n    /// @notice Thrown when registering a market that already exists.\n    error MarketAlreadyExists();\n    /// @notice Thrown when ordering on a market whose concentration cap is unset (disabled).\n    error ZeroProtocolConcentrationForMarket();\n    /// @notice Thrown when referencing a market that is not registered.\n    error MarketNotFound();\n    /// @notice Thrown when an order with a zero chainId is referenced.\n    error InvalidChainId();\n    /// @notice Thrown when a market's cover amount is below the configured minimum.\n    /// @param amount Provided cover amount, in canonical USD.\n    /// @param minimum Configured minimum, in canonical USD.\n    error OrderMarketCoverAmountTooLow(uint256 amount, uint256 minimum);\n\n    // -- commit / settle --\n    /// @notice Thrown when an order is not in PENDING status for the attempted action.\n    error OrderNotPending();\n    /// @notice Thrown when committing to a period that already has a commitment.\n    error PeriodAlreadyCommitted();\n    /// @notice Thrown when a commit or recommit is so late in the period that its grace window\n    ///         would reach the period end, leaving no instant at which settlement is possible.\n    error CommitTooCloseToPeriodEnd();\n    /// @notice Thrown when the commit/recommit period is not the current vault period.\n    /// @param commitmentPeriod Period the caller passed.\n    /// @param currentPeriod Current vault period at execution.\n    error InvalidCommitmentPeriod(uint256 commitmentPeriod, uint256 currentPeriod);\n    /// @notice Thrown when the Merkle root is the zero hash.\n    error InvalidMerkleRoot();\n    /// @notice Thrown when the declared/settled cover exceeds the effective capacity.\n    /// @param allocation Requested allocation, in canonical USD.\n    /// @param capacity Effective capacity ceiling, in canonical USD.\n    error TotalAllocationOverflow(uint256 allocation, uint256 capacity);\n    /// @notice Thrown when the caller's matching capacity exceeds the live capacity\n    ///         widened by the period's divergence tolerance.\n    /// @param matchingCapacity Capacity the matcher ran against, in canonical USD.\n    /// @param maxCapacity Live capacity ceiling (incl. tolerance), in canonical USD.\n    error MatchingCapacityOverflow(uint256 matchingCapacity, uint256 maxCapacity);\n    /// @notice Thrown when a market's allocated cover exceeds its requested cover.\n    /// @param allocation Allocated cover, in canonical USD.\n    /// @param capacity Requested cover for that market, in canonical USD.\n    error MarketAllocationOverflow(uint256 allocation, uint256 capacity);\n    /// @notice Thrown when cumulative settled cover for a concentration group exceeds its cap.\n    /// @param allocation Cumulative cover for the group, in canonical USD.\n    /// @param capacity Group cap, in canonical USD.\n    error ProtocolConcentrationOverflow(uint256 allocation, uint256 capacity);\n    /// @notice Thrown when cumulative settled cover exceeds the declared allocation.\n    /// @param allocation Cumulative settled cover, in canonical USD.\n    /// @param capacity Declared allocation, in canonical USD.\n    error TotalSettledOverflow(uint256 allocation, uint256 capacity);\n    /// @notice Thrown when the settle market list length differs from the order's markets.\n    error InvalidAllocationMarketsLength();\n    /// @notice Thrown when a settle market id does not match the order's market at that index.\n    error MarketIdMismatch();\n    /// @notice Thrown when an order settles with zero total allocated cover.\n    error ZeroAllocation();\n    /// @notice Thrown when there is no commitment for the period being settled/recommitted.\n    error NoCommitForPeriod();\n    /// @notice Thrown when the supplied Merkle proof does not verify against the commitment root.\n    error InvalidProof();\n    /// @notice Thrown when recommitting after settlement of the period has already started.\n    error SettlementsAlreadyStarted();\n    /// @notice Thrown when settling before the commitment's grace period has elapsed.\n    /// @param expiresAt Timestamp at which settlement becomes allowed.\n    error GracePeriodActive(uint48 expiresAt);\n    /// @notice Thrown when settling outside the order's settlement window (period advanced).\n    error SettleWindowExpired();\n    /// @notice Thrown when cancelling a non-expired order via the permissionless path.\n    error OrderNotExpired();\n    /// @notice Thrown when an order/orderId is otherwise invalid for the operation.\n    error InvalidOrder();\n\n    // -- admin / configuration --\n    /// @notice Thrown when a required address argument is the zero address.\n    error InvalidZeroAddress();\n    /// @notice Thrown when the configured leverage is zero.\n    error InvalidLeverage();\n    /// @notice Thrown when the configured minimum CAR is outside the supported 1.2x to 5x range.\n    error InvalidMinCAR();\n    /// @notice Thrown when the configured maximum price age is zero.\n    error InvalidMaxPriceAge();\n    /// @notice Thrown when the price feed adapter decimals are outside [6, 18].\n    /// @param decimals Reported adapter decimals.\n    error InvalidPriceFeedDecimals(uint8 decimals);\n    /// @notice Thrown when a concentration input is invalid (empty protocol or bps > 100%).\n    error InvalidProtocolConcentration();\n    /// @notice Thrown when the configured minimum order-market cover amount is zero.\n    error InvalidMinOrderMarketCoverAmount();\n    /// @notice Thrown when the configured divergence tolerance exceeds the hard ceiling.\n    /// @param bps Provided tolerance, in bps.\n    error InvalidDivergenceTolerance(uint16 bps);\n    /// @notice Thrown when the settlement grace period exceeds its ceiling relative to the\n    ///         current period duration.\n    /// @param gracePeriod Provided grace period, in seconds.\n    /// @param maxGracePeriod Maximum allowed grace period, in seconds.\n    error InvalidGracePeriod(uint48 gracePeriod, uint48 maxGracePeriod);\n    /// @notice Thrown when referencing a premium token that is not whitelisted.\n    error UnsupportedPremiumToken();\n    /// @notice Thrown when a token reports decimals greater than the canonical 18.\n    /// @param decimals Reported token decimals.\n    error UnsupportedDecimals(uint8 decimals);\n    /// @notice Thrown when adding a premium token that is already whitelisted.\n    error PremiumTokenAlreadySupported();\n    /// @notice Reserved: thrown when an action is blocked because matching is in progress.\n    error MatchingInProgress();\n    /// @notice Reserved: thrown when a period duration is invalid.\n    error InvalidPeriodDuration();\n\n    // =========================================================================\n    // Write functions\n    // =========================================================================\n\n    /// @notice Creates a cover order for the next period. Only CURATOR_ROLE.\n    /// @param buyer Account that will pay the premium.\n    /// @param payoutRecipient Account that receives the payout if a covered incident occurs.\n    /// @param beneficiaryAddress Off-chain beneficiary reference stored with the order.\n    /// @param premiumToken Whitelisted ERC20 used to pay the premium.\n    /// @param markets Per-market cover requests; `coverAmount` pre-normalized to canonical decimals.\n    /// @param orderType NEW or RENEWAL.\n    /// @return coverOrderId Id assigned to the new order.\n    function createCoverOrder(\n        address buyer,\n        address payoutRecipient,\n        string calldata beneficiaryAddress,\n        address premiumToken,\n        MarketAllocationInput[] calldata markets,\n        CoverOrderType orderType\n    ) external returns (uint256 coverOrderId);\n\n    /// @notice Commits a Merkle root with matching results. Only ALLOCATOR_ROLE.\n    /// @dev The vault asset price is read from the registered `priceFeedAdapter` oracle.\n    ///      Reverts if the grace window (`block.timestamp + settlementGracePeriod`) would\n    ///      reach the period end, since no order could ever settle against the commitment.\n    ///      Stores `matchingCapacity` — the capacity the off-chain matcher ran against —\n    ///      as the commitment's `totalAvailableCapacity`, so the committed tree can be\n    ///      re-derived exactly; the live recompute (widened by `divergenceToleranceBps`)\n    ///      only bounds it.\n    /// @param commitmentPeriod The period the caller intends to match. Must equal\n    ///        `vault.currentPeriod()` at execution time, otherwise the call reverts.\n    /// @param merkleRoot Root of the StandardMerkleTree containing settlement leaves.\n    ///        Each leaf encodes `(orderId, MarketCoverAllocation[])` with\n    ///        `allocatedCover` in canonical USD.\n    /// @param totalAllocated Sum of all allocated cover across all orders in the tree,\n    ///        in canonical USD. Must not exceed `matchingCapacity`.\n    /// @param matchingCapacity Capacity the matching ran against, in canonical USD. Must\n    ///        not exceed the live capacity widened by the period's divergence tolerance.\n    function commitAllocation(\n        uint256 commitmentPeriod,\n        bytes32 merkleRoot,\n        uint256 totalAllocated,\n        uint256 matchingCapacity\n    ) external;\n\n    /// @notice Settles a single order against the committed Merkle root. Only ALLOCATOR_ROLE.\n    /// @dev The premium is computed on-chain, pro-rata per market from the order's stored\n    ///      rates and the vault's period duration — never taken from the caller or the leaf.\n    /// @param orderId Order to settle.\n    /// @param marketCoverAllocations Per-market allocated cover, in canonical USD;\n    ///        order and market ids must match the order's markets.\n    /// @param proof Merkle proof of the leaf for this order against the period commitment root.\n    function settleCoverOrder(\n        uint256 orderId,\n        MarketCoverAllocation[] calldata marketCoverAllocations,\n        bytes32[] calldata proof\n    ) external;\n\n    /// @notice Settles multiple orders in a single transaction. Only ALLOCATOR_ROLE.\n    /// @param params Per-order settle parameters (orderId, allocations, proof).\n    function batchSettleCoverOrder(SettleParams[] calldata params) external;\n\n    /// @notice Cancels a pending cover order. Only CURATOR_ROLE.\n    /// @param coverOrderId Order to cancel; must still be PENDING.\n    function cancelCoverOrder(uint256 coverOrderId) external;\n\n    /// @notice Permissionlessly cancels PENDING orders whose cover period has already elapsed.\n    /// @dev Once `currentPeriod() > order.period` the settle window has closed and the order can\n    ///      never be settled; anyone may clean up the dangling PENDING state in batch.\n    /// @param coverOrderIds Ids of expired PENDING orders to cancel.\n    function cancelExpiredOrders(uint256[] calldata coverOrderIds) external;\n\n    /// @notice Replaces a committed Merkle root if no orders have been settled yet. Only CONFIG_ADMIN_ROLE.\n    /// @dev Restricted to the current period; the new matching capacity is bound to the\n    ///      period's real collateral within tolerance, recomputed from live inputs.\n    ///      Resets the commitment's `graceExpiresAt` from the current `settlementGracePeriod`,\n    ///      under the same period-end proximity check as `commitAllocation` — no commitment can\n    ///      ever store a window past its period end. Recommitting the same root is the supported\n    ///      way to re-derive a published window after a grace update; for a swap late in the\n    ///      period, lower the grace first so the fresh window fits, or use\n    ///      `cancelCommitAllocation` to withdraw the root without a replacement.\n    /// @param period Period whose commitment is replaced; must equal the current vault period.\n    /// @param newMerkleRoot New StandardMerkleTree root of settlement leaves.\n    /// @param newTotalAllocated New declared sum of allocated cover, in canonical USD.\n    /// @param newMatchingCapacity Capacity the new matching ran against, in canonical USD.\n    function recommitAllocation(\n        uint256 period,\n        bytes32 newMerkleRoot,\n        uint256 newTotalAllocated,\n        uint256 newMatchingCapacity\n    ) external;\n\n    /// @notice Cancels a period's commitment if no orders have been settled yet. Only CONFIG_ADMIN_ROLE.\n    /// @dev Emergency path to withdraw a bad Merkle root without providing a replacement and\n    ///      without touching the price feed (unlike `recommitAllocation`, it works while the\n    ///      oracle is down or stale). After cancelling, `commitAllocation` can be called again\n    ///      for the period; if no new commit lands, pending orders expire unsettled and can be\n    ///      cleaned up via `cancelExpiredOrders`.\n    /// @param period Period whose commitment is cancelled; must equal the current vault period.\n    function cancelCommitAllocation(uint256 period) external;\n\n    // =========================================================================\n    // Admin functions\n    // =========================================================================\n\n    /// @notice Sets the address that receives collected premiums. Only ADMIN_ROLE.\n    /// @param newCollector New premium collector; must be non-zero.\n    function setPremiumCollector(address newCollector) external;\n\n    /// @notice Whitelists a premium token and caches its decimals. Only CONFIG_ADMIN_ROLE.\n    /// @param token ERC20 to whitelist; must report `decimals() <= CANONICAL_DECIMALS`.\n    function addSupportedPremiumToken(address token) external;\n\n    /// @notice Removes a premium token from the whitelist. Only CONFIG_ADMIN_ROLE.\n    /// @param token ERC20 to remove.\n    function removeSupportedPremiumToken(address token) external;\n\n    /// @notice Pushes a new capacity configuration checkpoint. Only CONFIG_ADMIN_ROLE.\n    /// @dev Effective at currentPeriod() + 1 (or period 0 for the first configuration).\n    /// @param config New capacity configuration.\n    function setCapacityConfig(CapacityConfig calldata config) external;\n\n    /// @notice Replaces the vault-asset USD price feed adapter. Only ADMIN_ROLE.\n    /// @param newPriceFeedAdapter New adapter; must report decimals in [6, 18].\n    function setPriceFeedAdapter(IAggregatorV3 newPriceFeedAdapter) external;\n\n    /// @notice Sets the maximum tolerated price age. Only ADMIN_ROLE.\n    /// @param newMaxPriceAge New max age in seconds; must be non-zero.\n    function setMaxPriceAge(uint48 newMaxPriceAge) external;\n\n    /// @notice Minimum delay between `commitAllocation`/`recommitAllocation` and `settleCoverOrder`.\n    ///         Gives operators a grace window to swap a bad merkle root via\n    ///         `recommitAllocation` before any settle finalizes. Defaults to 0 (disabled).\n    ///         Hard-capped at 8 hours — at most a third of any period duration, since the\n    ///         vault enforces periods to be multiples of its SMALLEST_PERIOD_DURATION (1 day) —\n    ///         so the grace can never consume the settle window.\n    ///         Only affects future commitments: each commitment freezes its own\n    ///         `graceExpiresAt` at commit/recommit time, so no update can move (or kill) an\n    ///         already-published window. To re-derive a published window under a new grace,\n    ///         recommit the same root via `recommitAllocation`.\n    function setSettlementGracePeriod(uint48 newGracePeriod) external;\n\n    /// @notice Registers a new market. Only CONFIG_ADMIN_ROLE.\n    /// @param newMarket Market to register (chainId, protocol, market).\n    /// @return marketId Derived id of the registered market.\n    function addSupportedMarket(Market calldata newMarket) external returns (bytes32 marketId);\n\n    /// @notice Sets the maxProtocolConcentrationBps cap for a protocolConcentration group derived from (protocol, chainId).\n    /// @dev Affects ALL markets sharing the same (protocol, chainId). Effective from currentPeriod() + 1.\n    /// @param protocolConcentration Group key (chainId, protocol) and its new cap in bps.\n    function setProtocolConcentration(ProtocolConcentrationInput calldata protocolConcentration) external;\n\n    /// @notice Batch variant of {setProtocolConcentration}. Only CONFIG_ADMIN_ROLE.\n    /// @param protocolConcentrations Concentration inputs to apply.\n    function batchSetProtocolConcentration(ProtocolConcentrationInput[] calldata protocolConcentrations) external;\n\n    // =========================================================================\n    // View functions — all data needed for off-chain matching\n    // =========================================================================\n\n    /// @notice The internal canonical decimals used for all on-chain monetary values.\n    function CANONICAL_DECIMALS() external view returns (uint8);\n\n    /// @notice Returns the vault contract (use to call currentPeriod(), totalAssets(), periodConfigurationAtNumber()).\n    function vault() external view returns (IFirelightVault);\n\n    /// @notice Address receiving premium payments.\n    function premiumCollector() external view returns (address);\n\n    /// @notice The CoverNFT contract minted on settle (immutable, set in constructor).\n    function coverNFT() external view returns (CoverNFT);\n\n    /// @notice Chainlink-compatible oracle queried to price the vault asset against USD.\n    function priceFeedAdapter() external view returns (IAggregatorV3);\n\n    /// @notice Max age (seconds) tolerated on `priceFeedAdapter.latestRoundData().updatedAt`.\n    function maxPriceAge() external view returns (uint48);\n\n    /// @notice Grace period (seconds) enforced between commit and settlement.\n    function settlementGracePeriod() external view returns (uint48);\n\n    /// @notice Cached `decimals()` of the registered `priceFeedAdapter`.\n    function priceFeedDecimals() external view returns (uint8);\n\n    /// @notice Next orderId that will be assigned.\n    function nextCoverOrderId() external view returns (uint256);\n\n    /// @notice Full order struct for a given orderId.\n    function getCoverOrder(uint256 coverOrderId) external view returns (CoverOrder memory);\n\n    /// @notice Per-market allocations for an order (marketId, coverRateAnnual, coverAmount).\n    ///         `coverAmount` and `allocatedCoverAmount` are in canonical USD.\n    function getCoverOrderMarkets(uint256 coverOrderId) external view returns (MarketAllocation[] memory);\n\n    /// @notice Period, allocated cover, and payoutRecipient for a given (orderId, marketId) pair.\n    /// @return period Period the order belongs to. Zero when not found.\n    /// @return allocatedCoverAmount Amount allocated to that market on settle, in canonical\n    ///         USD. Zero when not found.\n    /// @return payoutRecipient EVM address that will receive the payout for this cover if a\n    ///         covered incident occurs. `address(0)` means the pair was not found.\n    function getCoverOrderMarketInfo(\n        uint256 coverOrderId,\n        bytes32 marketId\n    ) external view returns (uint256 period, uint256 allocatedCoverAmount, address payoutRecipient);\n\n    /// @notice All orderIds created for a given period.\n    function getCoverOrdersIdByPeriod(uint256 period) external view returns (uint256[] memory);\n\n    /// @notice Market configuration by marketId.\n    function getSupportedMarket(bytes32 marketId) external view returns (Market memory);\n\n    /// @notice All registered marketIds (including markets whose protocolConcentration cap is 0).\n    function getSupportedMarketIds() external view returns (bytes32[] memory);\n\n    /// @notice Whether a premium token is whitelisted.\n    function isPremiumTokenSupported(address token) external view returns (bool);\n\n    /// @notice All currently whitelisted premium tokens.\n    /// @return The set of supported premium token addresses.\n    function getSupportedPremiumTokens() external view returns (address[] memory);\n\n    /// @notice Effective capacity configuration at currentPeriod() + 1.\n    function getEffectiveCapacityConfig() external view returns (CapacityConfig memory);\n\n    /// @notice get active capacity config at a given period\n    function getCapacityConfigAt(uint256 period) external view returns (CapacityConfig memory);\n\n    /// @notice Committed matching data for a given period.\n    function getAllocationCommitment(uint256 period) external view returns (AllocationCommitment memory);\n\n    /// @notice All protocolConcentration hashes ever registered via setProtocolConcentration / initialize.\n    ///         May include entries currently set to 0 bps (disabled).\n    function getSupportedProtocolConcentrationHashes() external view returns (bytes32[] memory);\n\n    /// @notice Returns the (protocol, chainId) tuple that originated the protocolConcentration hash.\n    function getProtocolConcentrationFromHash(\n        bytes32 protocolConcentrationHash\n    ) external view returns (ProtocolConcentration memory);\n\n    /// @notice ProtocolConcentration cap (bps) effective at currentPeriod() + 1.\n    function getEffectiveProtocolConcentration(bytes32 protocolConcentrationHash) external view returns (uint256);\n\n    /// @notice ProtocolConcentration cap (bps) active at the given `period`. Reads from the\n    ///         checkpoint history — useful for auditing past settlements.\n    function getProtocolConcentrationAt(\n        bytes32 protocolConcentrationHash,\n        uint256 period\n    ) external view returns (uint256);\n\n    /// @notice Cumulative settled cover for a specific protocolConcentration group in a given period.\n    function getProtocolConcentrationSettledCover(\n        uint256 period,\n        bytes32 protocolConcentrationHash\n    ) external view returns (uint256);\n}\n"},{"file_path":"contracts/core/CoverNFT.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport {ERC721Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\nimport {ERC721EnumerableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol\";\nimport {ERC721PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol\";\n\n/**\n * @title CoverNFT\n * @notice Upgradeable ERC-721 token representing covers created by the CoverOrderAllocator.\n * The CoverOrderAllocator is expected to mint one NFT per settled cover order.\n *\n * @custom:security-contact securityreport@firelight.finance\n */\ncontract CoverNFT is\n    ERC721Upgradeable,\n    ERC721EnumerableUpgradeable,\n    ERC721PausableUpgradeable,\n    AccessControlUpgradeable\n{\n    /// @notice Role allowed to pause and unpause the contract.\n    bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n    /// @notice Role allowed to mint new NFTs.\n    bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n    /// @notice Role allowed to update the collection base URI.\n    bytes32 public constant URI_MANAGER_ROLE = keccak256(\"URI_MANAGER_ROLE\");\n\n    // --- ERC-7201 Namespaced Storage ---\n    /// @custom:storage-location erc7201:firelight.covernft.storage\n    struct CoverNFTStorage {\n        string baseURI;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"firelight.covernft.storage\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant STORAGE_LOCATION = 0x426682ee43cf77999495f05d99a85f0091c30c5f2afdd681b11771286cb00b00;\n\n    function _getStorage() private pure returns (CoverNFTStorage storage $) {\n        assembly {\n            $.slot := STORAGE_LOCATION\n        }\n    }\n\n    /**\n     * @notice Emitted when the base URI is updated.\n     * @param oldBaseURI Previous base URI.\n     * @param newBaseURI New base URI.\n     */\n    event BaseURIUpdated(string oldBaseURI, string newBaseURI);\n\n    /// @notice Thrown when admin is zero address.\n    error InvalidAdmin();\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @notice Initializes the CoverNFT contract.\n     * @param name_ ERC-721 token name.\n     * @param symbol_ ERC-721 token symbol.\n     * @param baseURI_ Initial base URI for token metadata. May be empty.\n     * @param admin Address granted DEFAULT_ADMIN_ROLE.\n     * @param minter Address granted MINTER_ROLE.\n     * @param pauser Address granted PAUSER_ROLE. May be zero address.\n     * @param uriManager Address granted URI_MANAGER_ROLE. May be zero address.\n     */\n    function initialize(\n        string memory name_,\n        string memory symbol_,\n        string memory baseURI_,\n        address admin,\n        address minter,\n        address pauser,\n        address uriManager\n    ) public initializer {\n        __ERC721_init(name_, symbol_);\n        __ERC721Enumerable_init();\n        __ERC721Pausable_init();\n        __AccessControl_init();\n\n        if (admin == address(0)) revert InvalidAdmin();\n\n        _grantRole(DEFAULT_ADMIN_ROLE, admin);\n\n        if (minter != address(0)) _grantRole(MINTER_ROLE, minter);\n        if (pauser != address(0)) _grantRole(PAUSER_ROLE, pauser);\n        if (uriManager != address(0)) _grantRole(URI_MANAGER_ROLE, uriManager);\n\n        _setBaseURI(baseURI_);\n    }\n\n    /**\n     * @notice Safely mints a new cover order NFT.\n     * @param to Address receiving the NFT.\n     * @param tokenId Token id to mint.\n     */\n    function safeMint(address to, uint256 tokenId) public onlyRole(MINTER_ROLE) {\n        _safeMint(to, tokenId);\n    }\n\n    /**\n     * @notice Updates the base URI used for token metadata.\n     * @param baseURI_ New base URI for token metadata. May be empty.\n     */\n    function setBaseURI(string memory baseURI_) public onlyRole(URI_MANAGER_ROLE) {\n        _setBaseURI(baseURI_);\n    }\n\n    /**\n     * @notice Pauses token transfers, minting, and burning.\n     */\n    function pause() public onlyRole(PAUSER_ROLE) {\n        _pause();\n    }\n\n    /**\n     * @notice Unpauses token transfers, minting, and burning.\n     */\n    function unpause() public onlyRole(PAUSER_ROLE) {\n        _unpause();\n    }\n\n    /**\n     * @dev Stores a new base URI for token metadata.\n     * @param baseURI_ New base URI for token metadata.\n     */\n    function _setBaseURI(string memory baseURI_) private {\n        CoverNFTStorage storage $ = _getStorage();\n        string memory oldBaseURI = $.baseURI;\n        $.baseURI = baseURI_;\n        emit BaseURIUpdated(oldBaseURI, baseURI_);\n    }\n\n    /**\n     * @notice Returns the base URI used by ERC-721 metadata functions to construct token URIs.\n     * @return Base URI for token metadata.\n     */\n    function _baseURI() internal view override returns (string memory) {\n        return _getStorage().baseURI;\n    }\n\n    // --- Required overrides --- //\n\n    /// @dev Resolves the {ERC721}, {ERC721Enumerable}, and {ERC721Pausable} `_update` hooks.\n    function _update(\n        address to,\n        uint256 tokenId,\n        address auth\n    ) internal override(ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721PausableUpgradeable) returns (address) {\n        return super._update(to, tokenId, auth);\n    }\n\n    /// @dev Resolves the {ERC721} and {ERC721Enumerable} `_increaseBalance` hooks.\n    function _increaseBalance(\n        address account,\n        uint128 value\n    ) internal override(ERC721Upgradeable, ERC721EnumerableUpgradeable) {\n        super._increaseBalance(account, value);\n    }\n\n    /// @notice Returns whether the contract implements `interfaceId` (ERC-165).\n    /// @dev Resolves the {ERC721}, {ERC721Enumerable}, and {AccessControl} implementations.\n    /// @param interfaceId Interface identifier to query.\n    /// @return True if the interface is supported.\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view override(ERC721Upgradeable, ERC721EnumerableUpgradeable, AccessControlUpgradeable) returns (bool) {\n        return super.supportsInterface(interfaceId);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol)\n// This file was procedurally generated from scripts/generate/templates/MerkleProof.js.\n\npragma solidity ^0.8.20;\n\nimport {Hashes} from \"./Hashes.sol\";\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the Merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates Merkle trees that are safe\n * against this attack out of the box.\n *\n * IMPORTANT: Consider memory side-effects when using custom hashing functions\n * that access memory in an unsafe way.\n *\n * NOTE: This library supports proof verification for merkle trees built using\n * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving\n * leaf inclusion in trees built using non-commutative hashing functions requires\n * additional logic that is not supported by this library.\n */\nlibrary MerkleProof {\n    /**\n     *@dev The multiproof provided is not valid.\n     */\n    error MerkleProofInvalidMultiproof();\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in memory with the default hashing function.\n     */\n    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProof(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leaves & pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in memory with the default hashing function.\n     */\n    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in memory with a custom hashing function.\n     */\n    function verify(\n        bytes32[] memory proof,\n        bytes32 root,\n        bytes32 leaf,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bool) {\n        return processProof(proof, leaf, hasher) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leaves & pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in memory with a custom hashing function.\n     */\n    function processProof(\n        bytes32[] memory proof,\n        bytes32 leaf,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = hasher(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in calldata with the default hashing function.\n     */\n    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProofCalldata(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leaves & pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in calldata with the default hashing function.\n     */\n    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in calldata with a custom hashing function.\n     */\n    function verifyCalldata(\n        bytes32[] calldata proof,\n        bytes32 root,\n        bytes32 leaf,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bool) {\n        return processProofCalldata(proof, leaf, hasher) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leaves & pre-images are assumed to be sorted.\n     *\n     * This version handles proofs in calldata with a custom hashing function.\n     */\n    function processProofCalldata(\n        bytes32[] calldata proof,\n        bytes32 leaf,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = hasher(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * This version handles multiproofs in memory with the default hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.\n     * The `leaves` must be validated independently. See {processMultiProof}.\n     */\n    function multiProofVerify(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProof(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * This version handles multiproofs in memory with the default hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     *\n     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,\n     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not\n     * validating the leaves elsewhere.\n     */\n    function processMultiProof(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofFlagsLen = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proof.length != proofFlagsLen + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](proofFlagsLen);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < proofFlagsLen; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = Hashes.commutativeKeccak256(a, b);\n        }\n\n        if (proofFlagsLen > 0) {\n            if (proofPos != proof.length) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[proofFlagsLen - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * This version handles multiproofs in memory with a custom hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.\n     * The `leaves` must be validated independently. See {processMultiProof}.\n     */\n    function multiProofVerify(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bool) {\n        return processMultiProof(proof, proofFlags, leaves, hasher) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * This version handles multiproofs in memory with a custom hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     *\n     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,\n     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not\n     * validating the leaves elsewhere.\n     */\n    function processMultiProof(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32[] memory leaves,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofFlagsLen = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proof.length != proofFlagsLen + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](proofFlagsLen);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < proofFlagsLen; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = hasher(a, b);\n        }\n\n        if (proofFlagsLen > 0) {\n            if (proofPos != proof.length) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[proofFlagsLen - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * This version handles multiproofs in calldata with the default hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.\n     * The `leaves` must be validated independently. See {processMultiProofCalldata}.\n     */\n    function multiProofVerifyCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * This version handles multiproofs in calldata with the default hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     *\n     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,\n     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not\n     * validating the leaves elsewhere.\n     */\n    function processMultiProofCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofFlagsLen = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proof.length != proofFlagsLen + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](proofFlagsLen);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < proofFlagsLen; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = Hashes.commutativeKeccak256(a, b);\n        }\n\n        if (proofFlagsLen > 0) {\n            if (proofPos != proof.length) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[proofFlagsLen - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * This version handles multiproofs in calldata with a custom hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.\n     * The `leaves` must be validated independently. See {processMultiProofCalldata}.\n     */\n    function multiProofVerifyCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bool) {\n        return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * This version handles multiproofs in calldata with a custom hashing function.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     *\n     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,\n     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not\n     * validating the leaves elsewhere.\n     */\n    function processMultiProofCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32[] memory leaves,\n        function(bytes32, bytes32) view returns (bytes32) hasher\n    ) internal view returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofFlagsLen = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proof.length != proofFlagsLen + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](proofFlagsLen);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < proofFlagsLen; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = hasher(a, b);\n        }\n\n        if (proofFlagsLen > 0) {\n            if (proofPos != proof.length) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[proofFlagsLen - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IERC721Metadata} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {ERC721Utils} from \"@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {ERC165Upgradeable} from \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport {IERC721Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721, IERC721Metadata, IERC721Errors {\n    using Strings for uint256;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC721\n    struct ERC721Storage {\n        // Token name\n        string _name;\n\n        // Token symbol\n        string _symbol;\n\n        mapping(uint256 tokenId => address) _owners;\n\n        mapping(address owner => uint256) _balances;\n\n        mapping(uint256 tokenId => address) _tokenApprovals;\n\n        mapping(address owner => mapping(address operator => bool)) _operatorApprovals;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC721\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC721StorageLocation = 0x80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab0079300;\n\n    function _getERC721Storage() private pure returns (ERC721Storage storage $) {\n        assembly {\n            $.slot := ERC721StorageLocation\n        }\n    }\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC721_init_unchained(name_, symbol_);\n    }\n\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n        ERC721Storage storage $ = _getERC721Storage();\n        $._name = name_;\n        $._symbol = symbol_;\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc IERC721\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        ERC721Storage storage $ = _getERC721Storage();\n        if (owner == address(0)) {\n            revert ERC721InvalidOwner(address(0));\n        }\n        return $._balances[owner];\n    }\n\n    /// @inheritdoc IERC721\n    function ownerOf(uint256 tokenId) public view virtual returns (address) {\n        return _requireOwned(tokenId);\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function name() public view virtual returns (string memory) {\n        ERC721Storage storage $ = _getERC721Storage();\n        return $._name;\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function symbol() public view virtual returns (string memory) {\n        ERC721Storage storage $ = _getERC721Storage();\n        return $._symbol;\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n        _requireOwned(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /// @inheritdoc IERC721\n    function approve(address to, uint256 tokenId) public virtual {\n        _approve(to, tokenId, _msgSender());\n    }\n\n    /// @inheritdoc IERC721\n    function getApproved(uint256 tokenId) public view virtual returns (address) {\n        _requireOwned(tokenId);\n\n        return _getApproved(tokenId);\n    }\n\n    /// @inheritdoc IERC721\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /// @inheritdoc IERC721\n    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n        ERC721Storage storage $ = _getERC721Storage();\n        return $._operatorApprovals[owner][operator];\n    }\n\n    /// @inheritdoc IERC721\n    function transferFrom(address from, address to, uint256 tokenId) public virtual {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n        address previousOwner = _update(to, tokenId, _msgSender());\n        if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /// @inheritdoc IERC721\n    function safeTransferFrom(address from, address to, uint256 tokenId) public {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /// @inheritdoc IERC721\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n        transferFrom(from, to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     *\n     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n     * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        ERC721Storage storage $ = _getERC721Storage();\n        return $._owners[tokenId];\n    }\n\n    /**\n     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n     */\n    function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n        ERC721Storage storage $ = _getERC721Storage();\n        return $._tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n     * particular (ignoring whether it is owned by `owner`).\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n        return\n            spender != address(0) &&\n            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n     * Reverts if:\n     * - `spender` does not have approval from `owner` for `tokenId`.\n     * - `spender` does not have approval to manage all of `owner`'s assets.\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n        if (!_isAuthorized(owner, spender, tokenId)) {\n            if (owner == address(0)) {\n                revert ERC721NonexistentToken(tokenId);\n            } else {\n                revert ERC721InsufficientApproval(spender, tokenId);\n            }\n        }\n    }\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n     *\n     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n     * remain consistent with one another.\n     */\n    function _increaseBalance(address account, uint128 value) internal virtual {\n        ERC721Storage storage $ = _getERC721Storage();\n        unchecked {\n            $._balances[account] += value;\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n     */\n    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n        ERC721Storage storage $ = _getERC721Storage();\n        address from = _ownerOf(tokenId);\n\n        // Perform (optional) operator check\n        if (auth != address(0)) {\n            _checkAuthorized(from, auth, tokenId);\n        }\n\n        // Execute the update\n        if (from != address(0)) {\n            // Clear approval. No need to re-authorize or emit the Approval event\n            _approve(address(0), tokenId, address(0), false);\n\n            unchecked {\n                $._balances[from] -= 1;\n            }\n        }\n\n        if (to != address(0)) {\n            unchecked {\n                $._balances[to] += 1;\n            }\n        }\n\n        $._owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        return from;\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner != address(0)) {\n            revert ERC721InvalidSender(address(0));\n        }\n    }\n\n    /**\n     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal {\n        address previousOwner = _update(address(0), tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        } else if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n     * are aware of the ERC-721 standard to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is like {safeTransferFrom} in the sense that it invokes\n     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `tokenId` token must exist and be owned by `from`.\n     * - `to` cannot be the zero address.\n     * - `from` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId) internal {\n        _safeTransfer(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is\n     * either the owner of the token, or approved to operate on all tokens held by this owner.\n     *\n     * Emits an {Approval} event.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address to, uint256 tokenId, address auth) internal {\n        _approve(to, tokenId, auth, true);\n    }\n\n    /**\n     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not\n     * emitted in the context of transfers.\n     */\n    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {\n        ERC721Storage storage $ = _getERC721Storage();\n        // Avoid reading the owner unless necessary\n        if (emitEvent || auth != address(0)) {\n            address owner = _requireOwned(tokenId);\n\n            // We do not use _isAuthorized because single-token approvals should not be able to call approve\n            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {\n                revert ERC721InvalidApprover(auth);\n            }\n\n            if (emitEvent) {\n                emit Approval(owner, to, tokenId);\n            }\n        }\n\n        $._tokenApprovals[tokenId] = to;\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Requirements:\n     * - operator can't be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        ERC721Storage storage $ = _getERC721Storage();\n        if (operator == address(0)) {\n            revert ERC721InvalidOperator(operator);\n        }\n        $._operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).\n     * Returns the owner.\n     *\n     * Overrides to ownership logic should be done to {_ownerOf}.\n     */\n    function _requireOwned(uint256 tokenId) internal view returns (address) {\n        address owner = _ownerOf(tokenId);\n        if (owner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n        return owner;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/draft-IERC6093.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Panic.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\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"},{"file_path":"@openzeppelin/contracts/utils/math/SignedMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\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, int256 a, int256 b) internal pure returns (int256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // Formula from the \"Bit Twiddling Hacks\" by Sean Eron Anderson.\n            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\n            // taking advantage of the most significant (or \"sign\" bit) in two's complement representation.\n            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\n            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\n            int256 mask = n >> 255;\n\n            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\n            return uint256((n + mask) ^ mask);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC4626.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC-4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC721Upgradeable} from \"../ERC721Upgradeable.sol\";\nimport {IERC721Enumerable} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability\n * of all the token ids in the contract as well as all token ids owned by each account.\n *\n * CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive},\n * interfere with enumerability and should not be used together with {ERC721Enumerable}.\n */\nabstract contract ERC721EnumerableUpgradeable is Initializable, ERC721Upgradeable, IERC721Enumerable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC721Enumerable\n    struct ERC721EnumerableStorage {\n        mapping(address owner => mapping(uint256 index => uint256)) _ownedTokens;\n        mapping(uint256 tokenId => uint256) _ownedTokensIndex;\n\n        uint256[] _allTokens;\n        mapping(uint256 tokenId => uint256) _allTokensIndex;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC721Enumerable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC721EnumerableStorageLocation = 0x645e039705490088daad89bae25049a34f4a9072d398537b1ab2425f24cbed00;\n\n    function _getERC721EnumerableStorage() private pure returns (ERC721EnumerableStorage storage $) {\n        assembly {\n            $.slot := ERC721EnumerableStorageLocation\n        }\n    }\n\n    /**\n     * @dev An `owner`'s token query was out of bounds for `index`.\n     *\n     * NOTE: The owner being `address(0)` indicates a global out of bounds index.\n     */\n    error ERC721OutOfBoundsIndex(address owner, uint256 index);\n\n    /**\n     * @dev Batch mint is not allowed.\n     */\n    error ERC721EnumerableForbiddenBatchMint();\n\n    function __ERC721Enumerable_init() internal onlyInitializing {\n    }\n\n    function __ERC721Enumerable_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721Upgradeable) returns (bool) {\n        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc IERC721Enumerable\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        if (index >= balanceOf(owner)) {\n            revert ERC721OutOfBoundsIndex(owner, index);\n        }\n        return $._ownedTokens[owner][index];\n    }\n\n    /// @inheritdoc IERC721Enumerable\n    function totalSupply() public view virtual returns (uint256) {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        return $._allTokens.length;\n    }\n\n    /// @inheritdoc IERC721Enumerable\n    function tokenByIndex(uint256 index) public view virtual returns (uint256) {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        if (index >= totalSupply()) {\n            revert ERC721OutOfBoundsIndex(address(0), index);\n        }\n        return $._allTokens[index];\n    }\n\n    /// @inheritdoc ERC721Upgradeable\n    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {\n        address previousOwner = super._update(to, tokenId, auth);\n\n        if (previousOwner == address(0)) {\n            _addTokenToAllTokensEnumeration(tokenId);\n        } else if (previousOwner != to) {\n            _removeTokenFromOwnerEnumeration(previousOwner, tokenId);\n        }\n        if (to == address(0)) {\n            _removeTokenFromAllTokensEnumeration(tokenId);\n        } else if (previousOwner != to) {\n            _addTokenToOwnerEnumeration(to, tokenId);\n        }\n\n        return previousOwner;\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's ownership-tracking data structures.\n     * @param to address representing the new owner of the given token ID\n     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n     */\n    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        uint256 length = balanceOf(to) - 1;\n        $._ownedTokens[to][length] = tokenId;\n        $._ownedTokensIndex[tokenId] = length;\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's token tracking data structures.\n     * @param tokenId uint256 ID of the token to be added to the tokens list\n     */\n    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        $._allTokensIndex[tokenId] = $._allTokens.length;\n        $._allTokens.push(tokenId);\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n     * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n     * @param from address representing the previous owner of the given token ID\n     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n     */\n    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = balanceOf(from);\n        uint256 tokenIndex = $._ownedTokensIndex[tokenId];\n\n        mapping(uint256 index => uint256) storage _ownedTokensByOwner = $._ownedTokens[from];\n\n        // When the token to delete is the last token, the swap operation is unnecessary\n        if (tokenIndex != lastTokenIndex) {\n            uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex];\n\n            _ownedTokensByOwner[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n            $._ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n        }\n\n        // This also deletes the contents at the last position of the array\n        delete $._ownedTokensIndex[tokenId];\n        delete _ownedTokensByOwner[lastTokenIndex];\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's token tracking data structures.\n     * This has O(1) time complexity, but alters the order of the _allTokens array.\n     * @param tokenId uint256 ID of the token to be removed from the tokens list\n     */\n    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n        ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();\n        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = $._allTokens.length - 1;\n        uint256 tokenIndex = $._allTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n        uint256 lastTokenId = $._allTokens[lastTokenIndex];\n\n        $._allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n        $._allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n        // This also deletes the contents at the last position of the array\n        delete $._allTokensIndex[tokenId];\n        $._allTokens.pop();\n    }\n\n    /**\n     * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch\n     */\n    function _increaseBalance(address account, uint128 amount) internal virtual override {\n        if (amount > 0) {\n            revert ERC721EnumerableForbiddenBatchMint();\n        }\n        super._increaseBalance(account, amount);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.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 Returns the addition of two unsigned integers, with an 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            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\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            // 512-bit multiply [prod1 prod0] = 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 = prod1 * 2²⁵⁶ + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= prod1) {\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 [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2²⁵⁶. 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 prod1\n            // is no longer required.\n            result = prod0 * 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 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 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        uint256 exp;\n        unchecked {\n            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);\n            value >>= exp;\n            result += exp;\n\n            result += SafeCast.toUint(value > 1);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + 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 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        uint256 isGt;\n        unchecked {\n            isGt = SafeCast.toUint(value > (1 << 128) - 1);\n            value >>= isGt * 128;\n            result += isGt * 16;\n\n            isGt = SafeCast.toUint(value > (1 << 64) - 1);\n            value >>= isGt * 64;\n            result += isGt * 8;\n\n            isGt = SafeCast.toUint(value > (1 << 32) - 1);\n            value >>= isGt * 32;\n            result += isGt * 4;\n\n            isGt = SafeCast.toUint(value > (1 << 16) - 1);\n            value >>= isGt * 16;\n            result += isGt * 2;\n\n            result += SafeCast.toUint(value > (1 << 8) - 1);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + 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"},{"file_path":"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC721Upgradeable} from \"../ERC721Upgradeable.sol\";\nimport {PausableUpgradeable} from \"../../../utils/PausableUpgradeable.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC-721 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract pause mechanism of the contract unreachable, and thus unusable.\n */\nabstract contract ERC721PausableUpgradeable is Initializable, ERC721Upgradeable, PausableUpgradeable {\n    function __ERC721Pausable_init() internal onlyInitializing {\n    }\n\n    function __ERC721Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {ERC721-_update}.\n     *\n     * Requirements:\n     *\n     * - the contract must not be paused.\n     */\n    function _update(\n        address to,\n        uint256 tokenId,\n        address auth\n    ) internal virtual override whenNotPaused returns (address) {\n        return super._update(to, tokenId, auth);\n    }\n}\n"},{"file_path":"contracts/core/interfaces/IFirelightVault.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title IFirelightVault\n * @notice Full external interface of {FirelightVault}, an ERC4626-compatible vault with\n *         delayed withdrawals, role-based access control, blocklisting, pausing,\n *         and historical balance/supply/assets checkpoints.\n *\n * @dev FirelightVault intentionally deviates from ERC4626: `withdraw` and `redeem` create a\n *      pending withdrawal request rather than transferring assets immediately. The shares\n *      are burned on request, and assets become claimable in a later period via\n *      `claimWithdraw`. The standard ERC4626 `Withdraw` event is NOT emitted; instead the\n *      lifecycle is tracked by `WithdrawRequest` and `CompleteWithdraw` events.\n *\n * @custom:security-contact securityreport@firelight.finance\n */\ninterface IFirelightVault is IERC4626, IAccessControl {\n    // -------------------------------------------------------------------------\n    // Structs\n    // -------------------------------------------------------------------------\n\n    /**\n     * @notice Configuration of a vault period.\n     * @param epoch Starting timestamp of this configuration.\n     * @param duration Period length in seconds. Must be a multiple of {SMALLEST_PERIOD_DURATION}.\n     * @param startingPeriod Period number assigned to `epoch`.\n     */\n    struct PeriodConfiguration {\n        uint48 epoch;\n        uint48 duration;\n        uint256 startingPeriod;\n    }\n\n    /**\n     * @notice Initial parameters for vault deployment, ABI-encoded as the `bytes` argument\n     *         of {initialize}.\n     * @param defaultAdmin Receives `DEFAULT_ADMIN_ROLE`.\n     * @param limitUpdater Receives `DEPOSIT_LIMIT_UPDATE_ROLE`.\n     * @param blocklister Receives `BLOCKLIST_ROLE`.\n     * @param pauser Receives `PAUSE_ROLE`.\n     * @param periodConfigurationUpdater Receives `PERIOD_CONFIGURATION_UPDATE_ROLE`.\n     * @param rescuer Receives `RESCUER_ROLE`.\n     * @param depositLimit Initial maximum total assets allowed in the vault.\n     * @param periodConfigurationDuration Initial period duration.\n     */\n    struct InitParams {\n        address defaultAdmin;\n        address limitUpdater;\n        address blocklister;\n        address pauser;\n        address periodConfigurationUpdater;\n        address rescuer;\n        uint256 depositLimit;\n        uint48 periodConfigurationDuration;\n    }\n\n    // -------------------------------------------------------------------------\n    // Events\n    // -------------------------------------------------------------------------\n\n    /// @notice Emitted when the vault's deposit limit is updated.\n    event DepositLimitUpdated(uint256 limit);\n\n    /// @notice Emitted when a new period configuration is added.\n    event PeriodConfigurationAdded(PeriodConfiguration periodConfiguration);\n\n    /// @notice Emitted when a withdrawal request is created.\n    event WithdrawRequest(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 period,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /// @notice Emitted when a withdrawal is successfully claimed for a given period.\n    event CompleteWithdraw(address indexed receiver, uint256 assets, uint256 period);\n\n    /// @notice Emitted when a `RESCUER_ROLE` holder rescues shares from a blocklisted address.\n    event SharesRescuedFromBlocklisted(address from, address to, uint256 rescuedShares);\n\n    /// @notice Emitted when a `RESCUER_ROLE` holder rescues pending withdrawals from a blocklisted address.\n    event WithdrawRescuedFromBlocklisted(address from, address to, uint256[] periods, uint256[] rescuedShares);\n\n    /// @notice Emitted when an incident payout is processed, including when no assets can be paid.\n    /// @param to The allowlisted payout receiver.\n    /// @param requestedAmount The requested payout amount, in vault asset units.\n    /// @param paidAmount The amount actually transferred, which may be less than requested or zero.\n    /// @param captureTimestamp The incident capture timestamp that determines the covered period and payout window.\n    event PayoutExecuted(address indexed to, uint256 requestedAmount, uint256 paidAmount, uint48 captureTimestamp);\n\n    /// @notice Emitted when a period's active incident flag is set.\n    /// @param period The period whose active incident flag was set.\n    /// @param active Whether the period has an active incident.\n    event ActiveIncidentUpdated(uint256 indexed period, bool active);\n\n    /// @notice Emitted when an address is added to the blocklist.\n    event AddedToBlocklist(address indexed account);\n\n    /// @notice Emitted when an address is removed from the blocklist.\n    event RemovedFromBlocklist(address indexed account);\n\n    /// @notice Emitted when an address is added to the payout allowlist.\n    event AddedToPayoutAllowlist(address indexed account);\n\n    /// @notice Emitted when an address is removed from the payout allowlist.\n    event RemovedFromPayoutAllowlist(address indexed account);\n\n    /// @notice Emitted when a total-assets checkpoint is recorded outside deposit/withdraw flows.\n    event TotalAssetsCheckpointed(uint256 totalAssets);\n\n    // -------------------------------------------------------------------------\n    // Errors\n    // -------------------------------------------------------------------------\n\n    /// @notice An account involved in the operation is blocklisted.\n    error BlocklistedAddress();\n\n    /// @notice The account is not blocklisted.\n    error NotBlocklistedAddress();\n\n    /// @notice A deposit or mint would increase total assets above the deposit limit.\n    error DepositLimitExceeded();\n\n    /// @notice The deposit limit is zero.\n    error InvalidDepositLimit();\n\n    /// @notice The period configuration epoch is too early or not aligned with a period boundary.\n    error InvalidPeriodConfigurationEpoch();\n\n    /// @notice The period duration is outside the allowed range or not a multiple of SMALLEST_PERIOD_DURATION.\n    error InvalidPeriodConfigurationDuration();\n\n    /// @notice The account has insufficient shares for the withdrawal or no shares to rescue.\n    error InsufficientShares();\n\n    /// @notice The underlying asset address is zero.\n    error InvalidAssetAddress();\n\n    /// @notice The default admin address is zero.\n    error InvalidAdminAddress();\n\n    /// @notice An account address required by the operation is zero.\n    error InvalidAddress();\n\n    /// @notice The requested amount is zero or converts to zero shares or assets.\n    error InvalidAmount();\n\n    /// @notice No period configuration applies to the query, or the withdrawal period has not ended.\n    error InvalidPeriod();\n\n    /// @notice A future period configuration is already scheduled.\n    error CurrentPeriodConfigurationNotLast();\n\n    /// @notice The array of withdrawal periods to rescue is empty.\n    error InvalidArrayLength();\n\n    /// @notice A withdrawal for the account and period has already been claimed.\n    /// @param period The period whose withdrawal has already been claimed.\n    error AlreadyClaimedPeriod(uint256 period);\n\n    /// @notice The account has no withdrawal shares or claimable assets for the period.\n    /// @param period The period with no withdrawal shares or claimable assets.\n    error NoWithdrawalAmount(uint256 period);\n\n    /// @notice The payout receiver is not on the payout allowlist.\n    error AccountNotAllowlisted();\n\n    /// @notice The capture period is neither the current period nor the previous period.\n    error InvalidCapturePeriod();\n\n    /// @notice An active incident in the current or previous period blocks deposits and mints.\n    error CurrentPeriodHasActiveIncident();\n\n    // -------------------------------------------------------------------------\n    // Role identifiers and protocol constants (auto-generated public getters)\n    // -------------------------------------------------------------------------\n\n    function DEPOSIT_LIMIT_UPDATE_ROLE() external view returns (bytes32);\n\n    function RESCUER_ROLE() external view returns (bytes32);\n\n    function BLOCKLIST_ROLE() external view returns (bytes32);\n\n    function PAUSE_ROLE() external view returns (bytes32);\n\n    function PAYOUT_ALLOWLIST_ROLE() external view returns (bytes32);\n\n    function PAYOUT_ROLE() external view returns (bytes32);\n\n    function INCIDENT_ROLE() external view returns (bytes32);\n\n    function CHECKPOINT_ROLE() external view returns (bytes32);\n\n    function PERIOD_CONFIGURATION_UPDATE_ROLE() external view returns (bytes32);\n\n    function SMALLEST_PERIOD_DURATION() external view returns (uint48);\n\n    function MAX_PERIOD_DURATION() external view returns (uint48);\n\n    // -------------------------------------------------------------------------\n    // Storage getters (auto-generated from public state variables)\n    // -------------------------------------------------------------------------\n\n    function depositLimit() external view returns (uint256);\n\n    function contractVersion() external view returns (uint256);\n\n    function pendingWithdrawAssets() external view returns (uint256);\n\n    function periodConfigurations(\n        uint256 index\n    ) external view returns (uint48 epoch, uint48 duration, uint256 startingPeriod);\n\n    function withdrawShares(uint256 period) external view returns (uint256);\n\n    function withdrawAssets(uint256 period) external view returns (uint256);\n\n    function withdrawSharesOf(uint256 period, address account) external view returns (uint256);\n\n    function isWithdrawClaimed(uint256 period, address account) external view returns (bool);\n\n    function isBlocklisted(address account) external view returns (bool);\n\n    // -------------------------------------------------------------------------\n    // Initialization\n    // -------------------------------------------------------------------------\n\n    /**\n     * @notice Initializes the FirelightVault contract.\n     * @param asset_ The underlying ERC20 token.\n     * @param name_ The name of the vault share token.\n     * @param symbol_ The symbol of the vault share token.\n     * @param initParams_ ABI-encoded {InitParams}.\n     */\n    function initialize(IERC20 asset_, string memory name_, string memory symbol_, bytes memory initParams_) external;\n\n    // -------------------------------------------------------------------------\n    // Period queries\n    // -------------------------------------------------------------------------\n\n    function periodConfigurationAtTimestamp(uint48 timestamp) external view returns (PeriodConfiguration memory);\n\n    function periodConfigurationAtNumber(uint256 periodNumber) external view returns (PeriodConfiguration memory);\n\n    function periodAtTimestamp(uint48 timestamp) external view returns (uint256);\n\n    function currentPeriodConfiguration() external view returns (PeriodConfiguration memory);\n\n    function currentPeriod() external view returns (uint256);\n\n    function currentPeriodStart() external view returns (uint48);\n\n    function currentPeriodEnd() external view returns (uint48);\n\n    function nextPeriodEnd() external view returns (uint48);\n\n    function periodConfigurationsLength() external view returns (uint256);\n\n    // -------------------------------------------------------------------------\n    // Historical (checkpointed) queries\n    // -------------------------------------------------------------------------\n\n    function balanceOfAt(address account, uint48 timestamp) external view returns (uint256);\n\n    function totalSupplyAt(uint48 timestamp) external view returns (uint256);\n\n    function totalAssetsAt(uint48 timestamp) external view returns (uint256);\n\n    function withdrawalsOf(uint256 period, address account) external view returns (uint256);\n\n    function isPeriodInPayoutWindow(uint256 period) external view returns (bool);\n\n    // -------------------------------------------------------------------------\n    // Withdrawal lifecycle\n    // -------------------------------------------------------------------------\n\n    /**\n     * @notice Claims a pending withdrawal for `period`.\n     * @dev Reverts if `period` has not yet ended, has already been claimed, or has no balance.\n     */\n    function claimWithdraw(uint256 period) external returns (uint256 assets);\n\n    // -------------------------------------------------------------------------\n    // Pausing (PausableUpgradeable)\n    // -------------------------------------------------------------------------\n\n    function paused() external view returns (bool);\n\n    function pause() external;\n\n    function unpause() external;\n\n    function hasActiveIncident(uint256 period) external view returns (bool);\n\n    function setActiveIncident(uint256 period, bool active) external;\n\n    // -------------------------------------------------------------------------\n    // Admin / configuration\n    // -------------------------------------------------------------------------\n\n    function updateDepositLimit(uint256 newLimit) external;\n\n    function addPeriodConfiguration(uint48 epoch, uint48 duration) external;\n\n    /**\n     * @notice Records a checkpoint of the current total assets. Requires `CHECKPOINT_ROLE`.\n     * @dev Called by the reward distributor after forwarding assets so historical\n     * `totalAssetsAt` lookups include them.\n     */\n    function checkpointTotalAssets() external;\n\n    // -------------------------------------------------------------------------\n    // Blocklist\n    // -------------------------------------------------------------------------\n\n    function addToBlocklist(address account) external;\n\n    function removeFromBlocklist(address account) external;\n\n    // -------------------------------------------------------------------------\n    // Payout allowlist\n    // -------------------------------------------------------------------------\n\n    /// @notice Adds an address to the payout allowlist. Requires PAYOUT_ALLOWLIST_ROLE.\n    /// @param account The address to add. Cannot be the zero address.\n    function addToPayoutAllowlist(address account) external;\n\n    /// @notice Removes an address from the payout allowlist. Requires PAYOUT_ALLOWLIST_ROLE.\n    /// @param account The address to remove.\n    function removeFromPayoutAllowlist(address account) external;\n\n    /// @notice Returns whether an address is on the payout allowlist.\n    /// @param account The address to query.\n    /// @return True if the address is allowlisted to receive payouts.\n    function isPayoutAllowlisted(address account) external view returns (bool);\n\n    // -------------------------------------------------------------------------\n    // Rescue\n    // -------------------------------------------------------------------------\n\n    function rescueSharesFromBlocklisted(address from, address to) external;\n\n    function rescueWithdrawFromBlocklisted(address from, address to, uint256[] calldata periods) external;\n\n    // -------------------------------------------------------------------------\n    // Payout\n    // -------------------------------------------------------------------------\n\n    function payout(address to, uint256 amount, uint48 captureTimestamp) external returns (uint256 paidAmount);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\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"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"CheckpointUnorderedInsertion","type":"error"},{"inputs":[],"name":"CommitTooCloseToPeriodEnd","type":"error"},{"inputs":[],"name":"DuplicateMarket","type":"error"},{"inputs":[{"internalType":"uint48","name":"expiresAt","type":"uint48"}],"name":"GracePeriodActive","type":"error"},{"inputs":[],"name":"InvalidAllocationMarketsLength","type":"error"},{"inputs":[{"internalType":"int256","name":"price","type":"int256"}],"name":"InvalidAssetPrice","type":"error"},{"inputs":[],"name":"InvalidAssetPriceUpdatedAt","type":"error"},{"inputs":[],"name":"InvalidChainId","type":"error"},{"inputs":[{"internalType":"uint256","name":"commitmentPeriod","type":"uint256"},{"internalType":"uint256","name":"currentPeriod","type":"uint256"}],"name":"InvalidCommitmentPeriod","type":"error"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"InvalidDivergenceTolerance","type":"error"},{"inputs":[{"internalType":"uint48","name":"gracePeriod","type":"uint48"},{"internalType":"uint48","name":"maxGracePeriod","type":"uint48"}],"name":"InvalidGracePeriod","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLeverage","type":"error"},{"inputs":[],"name":"InvalidMarketsLength","type":"error"},{"inputs":[],"name":"InvalidMarketsZeroValue","type":"error"},{"inputs":[],"name":"InvalidMaxPriceAge","type":"error"},{"inputs":[],"name":"InvalidMerkleRoot","type":"error"},{"inputs":[],"name":"InvalidMinCAR","type":"error"},{"inputs":[],"name":"InvalidMinOrderMarketCoverAmount","type":"error"},{"inputs":[],"name":"InvalidOrder","type":"error"},{"inputs":[],"name":"InvalidPeriodDuration","type":"error"},{"inputs":[{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"InvalidPriceFeedDecimals","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidProtocolConcentration","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"allocation","type":"uint256"},{"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"MarketAllocationOverflow","type":"error"},{"inputs":[],"name":"MarketAlreadyExists","type":"error"},{"inputs":[],"name":"MarketIdMismatch","type":"error"},{"inputs":[],"name":"MarketNotFound","type":"error"},{"inputs":[{"internalType":"uint256","name":"matchingCapacity","type":"uint256"},{"internalType":"uint256","name":"maxCapacity","type":"uint256"}],"name":"MatchingCapacityOverflow","type":"error"},{"inputs":[],"name":"MatchingInProgress","type":"error"},{"inputs":[],"name":"NoCommitForPeriod","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minimum","type":"uint256"}],"name":"OrderMarketCoverAmountTooLow","type":"error"},{"inputs":[],"name":"OrderNotExpired","type":"error"},{"inputs":[],"name":"OrderNotPending","type":"error"},{"inputs":[],"name":"PeriodAlreadyCommitted","type":"error"},{"inputs":[],"name":"PremiumTokenAlreadySupported","type":"error"},{"inputs":[{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint48","name":"maxPriceAge","type":"uint48"}],"name":"PriceFeedTooOld","type":"error"},{"inputs":[{"internalType":"uint256","name":"allocation","type":"uint256"},{"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"ProtocolConcentrationOverflow","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SettleWindowExpired","type":"error"},{"inputs":[],"name":"SettlementsAlreadyStarted","type":"error"},{"inputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"name":"StaleAssetPriceRound","type":"error"},{"inputs":[{"internalType":"uint256","name":"allocation","type":"uint256"},{"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"TotalAllocationOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"allocation","type":"uint256"},{"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"TotalSettledOverflow","type":"error"},{"inputs":[{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"UnsupportedDecimals","type":"error"},{"inputs":[],"name":"UnsupportedPremiumToken","type":"error"},{"inputs":[],"name":"ZeroAllocation","type":"error"},{"inputs":[],"name":"ZeroProtocolConcentrationForMarket","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"period","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"AllocationCommitmentCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"period","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalAvailableCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalAllocated","type":"uint256"}],"name":"AllocationCommitted","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"minCAR","type":"uint256"},{"internalType":"contract IERC20","name":"firstLossBufferToken","type":"address"},{"internalType":"uint16","name":"divergenceToleranceBps","type":"uint16"},{"internalType":"address","name":"firstLossBuffer","type":"address"},{"internalType":"uint256","name":"effectiveLeverage","type":"uint256"},{"internalType":"uint256","name":"minOrderMarketCoverAmount","type":"uint256"}],"indexed":false,"internalType":"struct ICoverOrderAllocator.CapacityConfig","name":"config","type":"tuple"}],"name":"CapacityConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"coverOrderId","type":"uint256"}],"name":"CoverOrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"coverOrderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"payoutRecipient","type":"address"},{"indexed":false,"internalType":"string","name":"beneficiaryAddress","type":"string"},{"indexed":false,"internalType":"address","name":"premiumToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalCoverAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPremiumAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weightedAvgRate","type":"uint256"},{"indexed":false,"internalType":"enum ICoverOrderAllocator.CoverOrderType","name":"orderType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"CoverOrderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"coverOrderId","type":"uint256"},{"indexed":false,"internalType":"enum ICoverOrderAllocator.CoverOrderStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"allocatedCoverAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocatedPremiumAmount","type":"uint256"}],"name":"CoverOrderSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"string","name":"protocol","type":"string"},{"indexed":false,"internalType":"bytes32","name":"market","type":"bytes32"}],"name":"MarketAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint48","name":"oldMaxPriceAge","type":"uint48"},{"indexed":false,"internalType":"uint48","name":"newMaxPriceAge","type":"uint48"}],"name":"MaxPriceAgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldCollector","type":"address"},{"indexed":false,"internalType":"address","name":"newCollector","type":"address"}],"name":"PremiumCollectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"PremiumTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"PremiumTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPriceFeedAdapter","type":"address"},{"indexed":false,"internalType":"uint8","name":"oldPriceFeedDecimals","type":"uint8"},{"indexed":false,"internalType":"address","name":"newPriceFeedAdapter","type":"address"},{"indexed":false,"internalType":"uint8","name":"newPriceFeedDecimals","type":"uint8"}],"name":"PriceFeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"protocol","type":"string"},{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"ProtocolConcentrationRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"oldShareBps","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newShareBps","type":"uint256"}],"name":"ProtocolConcentrationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint48","name":"oldGracePeriod","type":"uint48"},{"indexed":false,"internalType":"uint48","name":"newGracePeriod","type":"uint48"}],"name":"SettlementGracePeriodUpdated","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ALLOCATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CANONICAL_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONFIG_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"bytes32","name":"market","type":"bytes32"}],"internalType":"struct ICoverOrderAllocator.Market","name":"newMarket","type":"tuple"}],"name":"addSupportedMarket","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"addSupportedPremiumToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"uint256","name":"maxProtocolConcentrationBps","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.ProtocolConcentrationInput[]","name":"protocolConcentrations","type":"tuple[]"}],"name":"batchSetProtocolConcentration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"marketId","type":"bytes32"},{"internalType":"uint256","name":"allocatedCover","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.MarketCoverAllocation[]","name":"marketCoverAllocations","type":"tuple[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct ICoverOrderAllocator.SettleParams[]","name":"params","type":"tuple[]"}],"name":"batchSettleCoverOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"cancelCommitAllocation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"coverOrderId","type":"uint256"}],"name":"cancelCoverOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"coverOrderIds","type":"uint256[]"}],"name":"cancelExpiredOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"commitmentPeriod","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"totalAllocated","type":"uint256"},{"internalType":"uint256","name":"matchingCapacity","type":"uint256"}],"name":"commitAllocation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coverNFT","outputs":[{"internalType":"contract CoverNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"payoutRecipient","type":"address"},{"internalType":"string","name":"beneficiaryAddress","type":"string"},{"internalType":"address","name":"premiumToken","type":"address"},{"components":[{"internalType":"bytes32","name":"marketId","type":"bytes32"},{"internalType":"uint32","name":"coverRateAnnual","type":"uint32"},{"internalType":"uint256","name":"coverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.MarketAllocationInput[]","name":"markets","type":"tuple[]"},{"internalType":"enum ICoverOrderAllocator.CoverOrderType","name":"orderType","type":"uint8"}],"name":"createCoverOrder","outputs":[{"internalType":"uint256","name":"coverOrderId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"getAllocationCommitment","outputs":[{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint256","name":"totalAvailableCapacity","type":"uint256"},{"internalType":"uint256","name":"totalDeclaredAllocated","type":"uint256"},{"internalType":"uint256","name":"totalSettledCover","type":"uint256"},{"internalType":"uint256","name":"totalSettledPremium","type":"uint256"},{"internalType":"uint48","name":"graceExpiresAt","type":"uint48"}],"internalType":"struct ICoverOrderAllocator.AllocationCommitment","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"getCapacityConfigAt","outputs":[{"components":[{"internalType":"uint256","name":"minCAR","type":"uint256"},{"internalType":"contract IERC20","name":"firstLossBufferToken","type":"address"},{"internalType":"uint16","name":"divergenceToleranceBps","type":"uint16"},{"internalType":"address","name":"firstLossBuffer","type":"address"},{"internalType":"uint256","name":"effectiveLeverage","type":"uint256"},{"internalType":"uint256","name":"minOrderMarketCoverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.CapacityConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"coverOrderId","type":"uint256"}],"name":"getCoverOrder","outputs":[{"components":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum ICoverOrderAllocator.CoverOrderType","name":"orderType","type":"uint8"},{"internalType":"enum ICoverOrderAllocator.CoverOrderStatus","name":"status","type":"uint8"},{"internalType":"address","name":"payoutRecipient","type":"address"},{"internalType":"string","name":"beneficiaryAddress","type":"string"},{"internalType":"address","name":"premiumToken","type":"address"},{"internalType":"uint256","name":"totalCoverAmount","type":"uint256"},{"internalType":"uint256","name":"totalPremiumAmount","type":"uint256"},{"internalType":"uint256","name":"weightedAvgRate","type":"uint256"},{"internalType":"uint256","name":"allocatedCoverAmount","type":"uint256"},{"internalType":"uint256","name":"allocatedPremiumAmount","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.CoverOrder","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"coverOrderId","type":"uint256"},{"internalType":"bytes32","name":"marketId","type":"bytes32"}],"name":"getCoverOrderMarketInfo","outputs":[{"internalType":"uint256","name":"period","type":"uint256"},{"internalType":"uint256","name":"allocatedCoverAmount","type":"uint256"},{"internalType":"address","name":"payoutRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"coverOrderId","type":"uint256"}],"name":"getCoverOrderMarkets","outputs":[{"components":[{"internalType":"bytes32","name":"marketId","type":"bytes32"},{"internalType":"uint32","name":"coverRateAnnual","type":"uint32"},{"internalType":"uint256","name":"coverAmount","type":"uint256"},{"internalType":"uint256","name":"allocatedCoverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.MarketAllocation[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"getCoverOrdersIdByPeriod","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEffectiveCapacityConfig","outputs":[{"components":[{"internalType":"uint256","name":"minCAR","type":"uint256"},{"internalType":"contract IERC20","name":"firstLossBufferToken","type":"address"},{"internalType":"uint16","name":"divergenceToleranceBps","type":"uint16"},{"internalType":"address","name":"firstLossBuffer","type":"address"},{"internalType":"uint256","name":"effectiveLeverage","type":"uint256"},{"internalType":"uint256","name":"minOrderMarketCoverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.CapacityConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"}],"name":"getEffectiveProtocolConcentration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"},{"internalType":"uint256","name":"period","type":"uint256"}],"name":"getProtocolConcentrationAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"}],"name":"getProtocolConcentrationFromHash","outputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"}],"internalType":"struct ICoverOrderAllocator.ProtocolConcentration","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"},{"internalType":"bytes32","name":"protocolConcentrationHash","type":"bytes32"}],"name":"getProtocolConcentrationSettledCover","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"marketId","type":"bytes32"}],"name":"getSupportedMarket","outputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"bytes32","name":"market","type":"bytes32"}],"internalType":"struct ICoverOrderAllocator.Market","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedMarketIds","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedPremiumTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedProtocolConcentrationHashes","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IFirelightVault","name":"vault","type":"address"},{"internalType":"address","name":"premiumCollector","type":"address"},{"internalType":"contract CoverNFT","name":"coverNFT","type":"address"},{"internalType":"contract IAggregatorV3","name":"priceFeedAdapter","type":"address"},{"internalType":"uint48","name":"maxPriceAge","type":"uint48"},{"internalType":"address[]","name":"premiumTokens","type":"address[]"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"adminRole","type":"address"},{"internalType":"address","name":"curatorRole","type":"address"},{"internalType":"address","name":"allocatorRole","type":"address"},{"internalType":"address","name":"configAdminRole","type":"address"},{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"uint256","name":"maxProtocolConcentrationBps","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.ProtocolConcentrationInput[]","name":"initialProtocolConcentrations","type":"tuple[]"},{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"bytes32","name":"market","type":"bytes32"}],"internalType":"struct ICoverOrderAllocator.Market[]","name":"newMarkets","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"minCAR","type":"uint256"},{"internalType":"contract IERC20","name":"firstLossBufferToken","type":"address"},{"internalType":"uint16","name":"divergenceToleranceBps","type":"uint16"},{"internalType":"address","name":"firstLossBuffer","type":"address"},{"internalType":"uint256","name":"effectiveLeverage","type":"uint256"},{"internalType":"uint256","name":"minOrderMarketCoverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.CapacityConfig","name":"capacityConfig","type":"tuple"}],"internalType":"struct ICoverOrderAllocator.InitParams","name":"params","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isPremiumTokenSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPriceAge","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextCoverOrderId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"premiumCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedAdapter","outputs":[{"internalType":"contract IAggregatorV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"uint256","name":"newTotalAllocated","type":"uint256"},{"internalType":"uint256","name":"newMatchingCapacity","type":"uint256"}],"name":"recommitAllocation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeSupportedPremiumToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"minCAR","type":"uint256"},{"internalType":"contract IERC20","name":"firstLossBufferToken","type":"address"},{"internalType":"uint16","name":"divergenceToleranceBps","type":"uint16"},{"internalType":"address","name":"firstLossBuffer","type":"address"},{"internalType":"uint256","name":"effectiveLeverage","type":"uint256"},{"internalType":"uint256","name":"minOrderMarketCoverAmount","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.CapacityConfig","name":"config","type":"tuple"}],"name":"setCapacityConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"newMaxPriceAge","type":"uint48"}],"name":"setMaxPriceAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCollector","type":"address"}],"name":"setPremiumCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAggregatorV3","name":"newPriceFeedAdapter","type":"address"}],"name":"setPriceFeedAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"string","name":"protocol","type":"string"},{"internalType":"uint256","name":"maxProtocolConcentrationBps","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.ProtocolConcentrationInput","name":"protocolConcentration","type":"tuple"}],"name":"setProtocolConcentration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"newGracePeriod","type":"uint48"}],"name":"setSettlementGracePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"marketId","type":"bytes32"},{"internalType":"uint256","name":"allocatedCover","type":"uint256"}],"internalType":"struct ICoverOrderAllocator.MarketCoverAllocation[]","name":"marketCoverAllocations","type":"tuple[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"settleCoverOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlementGracePeriod","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IFirelightVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}