{"file_path":"smart-contracts-public/src/redemption/InstantRedemption.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\nimport \"@openzeppelin/contracts/access/manager/AccessManaged.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/utils/Pausable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../pricing/PriceRouter.sol\";\nimport \"./PayoutTokenRegistry.sol\";\nimport \"./RedemptionVault.sol\";\nimport \"../token/IShareToken.sol\";\nimport \"../compliance/IKYCRegistry.sol\";\nimport \"../deposit/FeeVault.sol\";\nimport \"../pricing/IRedemptionReserves.sol\";\n\n/**\n * @title InstantRedemption\n * @notice Processes redemptions immediately (when no window is open) with daily/global/user limits.\n * @dev Design notes for auditors (Certora):\n * - **Units**: Share price and payout-token price fetched from {PriceRouter} are WAD (1e18).\n *   Payout amounts are converted to token units using the token's decimals.\n * - **Limits**: Limits are derived from `highWatermark` (USD WAD) and expressed as bps; counters\n *   are tracked in *gross payout token units* for the active payout token and reset daily or\n *   when the active payout token changes intra-day (see `dayPayoutToken`).\n * - **Safety**: Reentrancy guarded; authorization via {AccessManaged}. KYC enforced.\n * - **Accounting**: High-watermark is updated on daily reset when capacity increases.\n * - **Events**: Emits detailed events for processing, resets and refills.\n * - **Fees**: If feeBps > 0, fees are paid into a configured {FeeVault} instance via the {recorder} API.\n */\ncontract InstantRedemption is AccessManaged, ReentrancyGuard, Pausable {\n    using SafeERC20 for IERC20;\n    using Math for uint256;\n\n    // ============ State ============\n    IShareToken public immutable shareToken;\n    RedemptionVault public immutable vault;\n    PayoutTokenRegistry public immutable payoutTokenRegistry;\n    PriceRouter public immutable redemptionPriceRouter;\n    IKYCRegistry public immutable kyc;\n    address public immutable custodialWallet;\n\n    uint256 public highWatermark; // In WAD format for comparisons\n    uint256 public dailyLimitBps = 2000; // 20% default\n    uint256 public userLimitBps = 1000; // 10% default\n    uint256 public minRedemption = 10e18; // $10 minimum in WAD\n    uint256 public maxRedemption = 1_000_000e18; // $1M maximum in WAD\n    uint16 public feeBps; // Fee in basis points\n    FeeVault public feeVault; // Set per-product\n\n    uint256 public lastDailyReset; // Timestamp of last daily reset\n\n    // Global daily tracking\n    uint256 public currentDay;\n    uint256 public dailyGrossSpending;\n\n    /// @notice The payout token in effect for the current day's counters\n    address public dayPayoutToken;\n\n    /// @notice The redemption reserve calculator\n    IRedemptionReserves public redemptionReserves;\n\n    // User-specific daily tracking (properly resets per user)\n    struct UserDaily {\n        uint256 lastResetDay;\n        uint256 spending;\n    }\n\n    mapping(address => UserDaily) public userDailyTracking;\n\n    // ============ Constants ============\n    uint256 private constant BPS_DENOMINATOR = 10000;\n    uint256 private constant MAX_FEE_BPS = 1000; // 10%\n    uint256 private constant WAD = 1e18;\n    uint256 private constant DAY_DURATION = 1 days;\n    uint256 private constant VAULT_LOW_BALANCE_BPS = 2500; // 25% threshold\n\n    // ============ Events ============\n    event InstantRedemptionProcessed(\n        address indexed user,\n        uint256 sharesBurned,\n        uint256 grossPayout,\n        uint256 feeAmount,\n        uint256 netPayout\n    );\n    event HighWatermarkUpdated(uint256 oldValue, uint256 newValue);\n    event LimitsUpdated(uint256 dailyBps, uint256 userBps);\n    event RedemptionRangeUpdated(uint256 min, uint256 max);\n    event FeeUpdated(uint16 feeBps);\n    event DailyReset(uint256 totalCapacity, uint256 newHighWatermark);\n    event RefillNeeded(uint256 currentBalance, uint256 threshold, uint256 dailyLimit);\n\n    /// @notice Emitted when the active payout token changes mid-day and we hard-reset daily counters\n    event DailyResetByTokenSwitch(\n        address indexed previousToken, address indexed newToken, uint256 indexed day\n    );\n    event FeeVaultSet(address indexed feeVault);\n\n    // ============ Errors ============\n    error InvalidAmount();\n    error BelowMinimum();\n    error ExceedsMaximum();\n    error GlobalLimitExceeded();\n    error UserLimitExceeded();\n    error InsufficientOutput();\n    error InvalidConfiguration();\n    error ZeroAddress();\n    error KYCRequired();\n    error InvalidDecimals();\n\n    // ============ Constructor ============\n\n    constructor(\n        address _accessManager,\n        address _shareToken,\n        address _vault,\n        address _tokenRegistry,\n        address _priceRouter,\n        address _kyc,\n        address _custodialWallet,\n        address _redemptionReserves\n    ) AccessManaged(_accessManager) {\n        if (_shareToken == address(0)) revert ZeroAddress();\n        if (_vault == address(0)) revert ZeroAddress();\n        if (_tokenRegistry == address(0)) revert ZeroAddress();\n        if (_priceRouter == address(0)) revert ZeroAddress();\n        if (_kyc == address(0)) revert ZeroAddress();\n        if (_custodialWallet == address(0)) revert ZeroAddress();\n        if (_redemptionReserves == address(0)) revert ZeroAddress();\n        if (IERC20Metadata(_shareToken).decimals() != 18) revert InvalidDecimals();\n\n        shareToken = IShareToken(_shareToken);\n        vault = RedemptionVault(_vault);\n        payoutTokenRegistry = PayoutTokenRegistry(_tokenRegistry);\n        redemptionPriceRouter = PriceRouter(_priceRouter);\n        kyc = IKYCRegistry(_kyc);\n        custodialWallet = _custodialWallet;\n        lastDailyReset = block.timestamp;\n        redemptionReserves = IRedemptionReserves(_redemptionReserves);\n\n        // Pin the current day and the payout token used for this day (if configured)\n        currentDay = _getCurrentDay();\n        dayPayoutToken = payoutTokenRegistry.activePayoutToken();\n\n        // Roles are now managed by AccessManager\n\n        // Initialize highWatermark from current capacity to prevent DoS\n        // This ensures the system is immediately usable after deployment\n        uint256 initialCapacity = _calculateCapacityWad();\n        if (initialCapacity > 0) {\n            highWatermark = initialCapacity;\n            emit HighWatermarkUpdated(0, initialCapacity);\n        }\n    }\n\n    // ============ Redemption Functions ============\n\n    /**\n     * @notice Process instant redemption for a user (gateway call)\n     * @param user The actual user redeeming\n     * @param shares Amount of shares to redeem\n     * @param minPayout Minimum payout acceptable\n     */\n    function redeemFor(address user, uint256 shares, uint256 minPayout) external restricted {\n        _processRedemption(user, shares, minPayout);\n    }\n\n    /**\n     * @notice Internal redemption logic\n     * @param user The user performing redemption\n     * @param shares Amount of shares to redeem\n     * @param minPayout Minimum payout acceptable\n     */\n    function _processRedemption(address user, uint256 shares, uint256 minPayout)\n        internal\n        nonReentrant\n        whenNotPaused\n    {\n        if (shares == 0) revert InvalidAmount();\n        if (!kyc.isKYCApproved(user)) revert KYCRequired();\n\n        // Refresh daily state unconditionally: handles new day, high watermark updates,\n        // and mid-day payout token switches atomically.\n        _refreshDailyState();\n\n        // Get payout token (post ensure)\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n\n        // Calculate USD value and payout amount\n        (uint256 usdValue, uint256 grossPayout) = _calculateRedemption(shares, payoutToken);\n\n        // Check redemption limits in USD\n        if (usdValue < minRedemption) revert BelowMinimum();\n        if (usdValue > maxRedemption) revert ExceedsMaximum();\n\n        if (dailyGrossSpending + grossPayout > _getDailyLimit()) revert GlobalLimitExceeded();\n\n        // Update user-specific daily tracking with proper reset\n        uint256 userSpending = _getUserDailySpending(user);\n        if (userSpending + grossPayout > _getUserLimit()) revert UserLimitExceeded();\n\n        // Update spending\n        dailyGrossSpending += grossPayout;\n\n        // Update user tracking with proper day reset\n        UserDaily storage userDaily = userDailyTracking[user];\n        uint256 today = _getCurrentDay();\n        if (today > userDaily.lastResetDay) {\n            userDaily.lastResetDay = today;\n            userDaily.spending = grossPayout;\n        } else {\n            userDaily.spending = userSpending + grossPayout;\n        }\n\n        // Calculate fee and net payout\n        uint256 fee = (grossPayout * feeBps) / BPS_DENOMINATOR;\n        uint256 netPayout = grossPayout - fee;\n\n        // Check slippage protection\n        if (netPayout < minPayout) revert InsufficientOutput();\n\n        // Transfer shares from user directly (delegation pattern) and burn\n        IERC20(address(shareToken)).safeTransferFrom(user, address(this), shares);\n        shareToken.burn(address(this), shares);\n\n        // Transfer payout\n        vault.withdraw(payoutToken, user, netPayout);\n\n        // Transfer fee if applicable\n        if (fee > 0) {\n            vault.withdraw(payoutToken, address(feeVault), fee);\n            feeVault.recordFee(payoutToken, fee);\n        }\n\n        // Check if vault needs refill after withdrawal\n        _checkVaultBalance(payoutToken);\n\n        emit InstantRedemptionProcessed(user, shares, grossPayout, fee, netPayout);\n    }\n\n    // ============ Admin Functions ============\n\n    /**\n     * @notice Update high watermark to match current reserves\n     * @dev Operator can set to any value including zero. System self-heals if zero.\n     */\n    function updateHighWatermark() external restricted {\n        uint256 capacityWad = _calculateCapacityWad();\n        uint256 oldWatermark = highWatermark;\n        highWatermark = capacityWad;\n        emit HighWatermarkUpdated(oldWatermark, capacityWad);\n    }\n\n    /**\n     * @notice Update limit percentages\n     */\n    function updateLimitPercentages(uint256 _dailyBps, uint256 _userBps) external restricted {\n        if (_dailyBps == 0 || _dailyBps > BPS_DENOMINATOR) revert InvalidConfiguration();\n        if (_userBps == 0 || _userBps > _dailyBps) revert InvalidConfiguration();\n\n        dailyLimitBps = _dailyBps;\n        userLimitBps = _userBps;\n\n        emit LimitsUpdated(_dailyBps, _userBps);\n    }\n\n    /**\n     * @notice Update redemption range\n     */\n    function updateRedemptionRange(uint256 _min, uint256 _max) external restricted {\n        if (_min == 0 || _max <= _min) revert InvalidConfiguration();\n\n        minRedemption = _min;\n        maxRedemption = _max;\n\n        emit RedemptionRangeUpdated(_min, _max);\n    }\n\n    /**\n     * @notice Update fee bps (0 to 1000 / 10%)\n     */\n    function updateFee(uint16 _feeBps) external restricted {\n        if (_feeBps > MAX_FEE_BPS) revert InvalidConfiguration();\n        if (_feeBps > 0 && address(feeVault) == address(0)) revert ZeroAddress();\n        feeBps = _feeBps;\n        emit FeeUpdated(_feeBps);\n    }\n\n    /**\n     * @notice Pause redemptions\n     */\n    function pause() external restricted {\n        _pause();\n    }\n\n    /**\n     * @notice Unpause redemptions\n     */\n    function unpause() external restricted {\n        _unpause();\n    }\n\n    // ============ Public View Functions ============\n\n    /**\n     * @notice Get total capacity (vault + custodial wallet)\n     * @return Total payout tokens available in the system\n     */\n    function getTotalCapacity() public view returns (uint256) {\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n        uint256 vaultBalance = IERC20(payoutToken).balanceOf(address(vault));\n        uint256 custodialBalance = IERC20(payoutToken).balanceOf(custodialWallet);\n        return vaultBalance + custodialBalance;\n    }\n\n    // ============ View Functions ============\n\n    /**\n     * @notice Get current global daily redemption info\n     */\n    function getDailyRedemptions() external view returns (uint256 day, uint256 spending) {\n        uint256 today = _getCurrentDay();\n        address currentToken = payoutTokenRegistry.activePayoutToken();\n        if (today > currentDay || (currentToken != address(0) && currentToken != dayPayoutToken)) {\n            return (today, 0);\n        }\n        return (currentDay, dailyGrossSpending);\n    }\n\n    /**\n     * @notice Get user's current daily spending\n     * @param user User address\n     * @return Current day's spending for the user\n     */\n    function getUserDailySpending(address user) external view returns (uint256) {\n        return _getUserDailySpending(user);\n    }\n\n    /**\n     * @notice Preview redemption without executing\n     * @param user User address\n     * @param shares Amount of shares\n     * @return grossPayout Gross payout amount\n     * @return fee Fee amount\n     * @return netPayout Net payout after fee\n     * @return available Whether redemption would succeed\n     */\n    function previewRedemption(address user, uint256 shares)\n        external\n        view\n        returns (uint256 grossPayout, uint256 fee, uint256 netPayout, bool available)\n    {\n        // Check basic requirements\n        if (shares == 0 || !kyc.isKYCApproved(user)) {\n            return (0, 0, 0, false);\n        }\n\n        // Get payout token and calculate amounts\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n        (uint256 usdValue, uint256 gross) = _calculateRedemption(shares, payoutToken);\n\n        // Check limits\n        if (usdValue < minRedemption || usdValue > maxRedemption) {\n            return (0, 0, 0, false);\n        }\n\n        // Check daily limits (simulate reset if needed)\n        bool isNewDayOrToken = currentDay < _getCurrentDay()\n            || (\n                payoutTokenRegistry.activePayoutToken() != address(0)\n                    && payoutTokenRegistry.activePayoutToken() != dayPayoutToken\n            );\n\n        uint256 todayGlobalSpending = isNewDayOrToken ? 0 : dailyGrossSpending;\n        if (todayGlobalSpending + gross > _getDailyLimit()) {\n            return (0, 0, 0, false);\n        }\n\n        uint256 userSpending = _getUserDailySpending(user);\n        if (userSpending + gross > _getUserLimit()) {\n            return (0, 0, 0, false);\n        }\n\n        // Calculate fee and net\n        uint256 feeAmount = (gross * feeBps) / BPS_DENOMINATOR;\n        uint256 net = gross - feeAmount;\n\n        return (gross, feeAmount, net, true);\n    }\n\n    /**\n     * @notice Get the vault low balance threshold (25% of daily limit)\n     * @return Threshold amount in payout token decimals\n     */\n    function getVaultLowBalanceThreshold() public view returns (uint256) {\n        uint256 dailyLimit = _getDailyLimit();\n        return (dailyLimit * VAULT_LOW_BALANCE_BPS) / BPS_DENOMINATOR;\n    }\n\n    /**\n     * @notice Get remaining daily limit\n     * @return Amount remaining in payout token decimals\n     */\n    function getRemainingDailyLimit() public view returns (uint256) {\n        bool isNewDayOrToken = currentDay < _getCurrentDay()\n            || (\n                payoutTokenRegistry.activePayoutToken() != address(0)\n                    && payoutTokenRegistry.activePayoutToken() != dayPayoutToken\n            );\n\n        uint256 todaySpending = isNewDayOrToken ? 0 : dailyGrossSpending;\n        uint256 dailyLimit = _getDailyLimit();\n        return dailyLimit > todaySpending ? dailyLimit - todaySpending : 0;\n    }\n\n    /**\n     * @notice Get remaining user limit for a specific user\n     * @param user The user to check\n     * @return Amount remaining in payout token decimals\n     */\n    function getRemainingUserLimit(address user) public view returns (uint256) {\n        uint256 userSpending = _getUserDailySpending(user);\n        uint256 userLimit = _getUserLimit();\n        return userLimit > userSpending ? userLimit - userSpending : 0;\n    }\n\n    /**\n     * @notice Get comprehensive redemption status for a user\n     * @param user The user to check\n     * @return kycApproved Whether user is KYC approved\n     * @return remainingDaily Remaining daily limit in payout token decimals\n     * @return remainingUser Remaining user limit in payout token decimals\n     * @return minRedemptionAmount Minimum redemption amount in WAD\n     * @return maxRedemptionAmount Maximum redemption amount in WAD\n     * @return currentFee Current fee in basis points\n     */\n    function getRedemptionStatus(address user)\n        public\n        view\n        returns (\n            bool kycApproved,\n            uint256 remainingDaily,\n            uint256 remainingUser,\n            uint256 minRedemptionAmount,\n            uint256 maxRedemptionAmount,\n            uint256 currentFee\n        )\n    {\n        kycApproved = kyc.isKYCApproved(user);\n        remainingDaily = getRemainingDailyLimit();\n        remainingUser = getRemainingUserLimit(user);\n        minRedemptionAmount = minRedemption;\n        maxRedemptionAmount = maxRedemption;\n        currentFee = feeBps;\n    }\n\n    /**\n     * @notice Set the FeeVault used to collect protocol fees on claims\n     */\n    function setFeeVault(address _feeVault) external restricted {\n        if (_feeVault == address(0)) revert ZeroAddress();\n        feeVault = FeeVault(_feeVault);\n        emit FeeVaultSet(_feeVault);\n    }\n\n    // ============ Internal Functions ============\n\n    /**\n     * @notice Calculate redemption amounts\n     */\n    function _calculateRedemption(uint256 shares, address payoutToken)\n        private\n        view\n        returns (uint256 usdValue, uint256 grossPayout)\n    {\n        // Get prices from router\n        uint256 sharePrice = redemptionPriceRouter.getPrice(address(shareToken));\n        uint256 payoutPrice = redemptionPriceRouter.getPrice(payoutToken);\n\n        // Calculate USD value of shares\n        usdValue = Math.mulDiv(shares, sharePrice, WAD);\n\n        // Calculate payout amount in token decimals\n        uint8 payoutDecimals = IERC20Metadata(payoutToken).decimals();\n        if (payoutDecimals > 24) revert InvalidDecimals();\n        grossPayout = Math.mulDiv(usdValue, 10 ** payoutDecimals, payoutPrice);\n    }\n\n    /**\n     * @notice Refresh daily state atomically.\n     * @dev Consolidates daily reset and token switch handling.\n     *\n     * Invariants after return:\n     * - `currentDay` equals `_getCurrentDay()`.\n     * - `dayPayoutToken` matches `payoutTokenRegistry.activePayoutToken()`.\n     * - `dailyGrossSpending` is zeroed when the UTC day or payout token changed.\n     *\n     * Emits:\n     * - `DailyReset` when a new day starts (also updates `highWatermark` if capacity grew).\n     * - `DailyResetByTokenSwitch` when the token changes mid-day.\n     *\n     * Should be called unconditionally at the start of `_processRedemption()`.\n     */\n    function _refreshDailyState() private {\n        uint256 today = _getCurrentDay();\n        uint256 lastResetDay = lastDailyReset / DAY_DURATION;\n        address currentToken = payoutTokenRegistry.activePayoutToken();\n\n        // New day or initialization path\n        if (today > lastResetDay || highWatermark == 0) {\n            // Calculate current capacity in USD WAD\n            uint256 totalCapacityWad = _calculateCapacityWad();\n\n            // Update high watermark if capacity increased\n            uint256 oldWatermark = highWatermark;\n            if (totalCapacityWad > highWatermark) {\n                highWatermark = totalCapacityWad;\n                emit HighWatermarkUpdated(oldWatermark, totalCapacityWad);\n            }\n\n            // Reset day timestamp & pin today's payout token\n            lastDailyReset = block.timestamp;\n            currentDay = today;\n            dayPayoutToken = currentToken;\n\n            // Reset global daily counters for the new day\n            dailyGrossSpending = 0;\n\n            emit DailyReset(totalCapacityWad, highWatermark);\n            return;\n        }\n\n        // Same day: if payout token switched, hard reset today's counters\n        if (currentToken != address(0) && currentToken != dayPayoutToken) {\n            address previousToken = dayPayoutToken;\n            dayPayoutToken = currentToken;\n            dailyGrossSpending = 0;\n            emit DailyResetByTokenSwitch(previousToken, currentToken, today);\n        }\n\n        // Safety: if currentDay lags today (shouldn't happen), sync it\n        if (today > currentDay) {\n            currentDay = today;\n        }\n    }\n\n    /**\n     * @notice Get user's daily spending with proper reset\n     * @param user User address\n     * @return Current spending amount\n     */\n    function _getUserDailySpending(address user) private view returns (uint256) {\n        UserDaily storage userDaily = userDailyTracking[user];\n        uint256 today = _getCurrentDay();\n        address currentToken = payoutTokenRegistry.activePayoutToken();\n\n        // Treat token mismatch like a new day for all users\n        if (\n            today > userDaily.lastResetDay\n                || (currentToken != address(0) && currentToken != dayPayoutToken)\n        ) {\n            return 0;\n        }\n        return userDaily.spending;\n    }\n\n    /**\n     * @notice Get current day index\n     */\n    function _getCurrentDay() private view returns (uint256) {\n        return block.timestamp / DAY_DURATION;\n    }\n\n    /**\n     * @notice Calculate current total capacity in USD WAD\n     * @dev Converts token balances to USD value using price from router\n     */\n    function _calculateCapacityWad() private view returns (uint256) {\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n        if (payoutToken == address(0)) return 0;\n\n        return redemptionReserves.calculateTotalReserveValue(address(vault), custodialWallet);\n    }\n\n    /**\n     * @notice Get daily limit in payout token decimals\n     * @dev Converts USD limit to token amount using current price\n     */\n    function _getDailyLimit() private view returns (uint256) {\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n        uint8 decimals = IERC20Metadata(payoutToken).decimals();\n        if (decimals > 24) revert InvalidDecimals();\n\n        // Calculate limit in USD WAD\n        uint256 limitInUsdWad = (highWatermark * dailyLimitBps) / BPS_DENOMINATOR;\n\n        // Get payout token price in USD WAD\n        uint256 payoutPriceWad = redemptionPriceRouter.getPrice(payoutToken);\n\n        // Convert USD limit to token amount\n        // tokens = (USD * 10^decimals) / price\n        return Math.mulDiv(limitInUsdWad, 10 ** decimals, payoutPriceWad);\n    }\n\n    /**\n     * @notice Get user limit in payout token decimals\n     * @dev Converts USD limit to token amount using current price\n     */\n    function _getUserLimit() private view returns (uint256) {\n        address payoutToken = payoutTokenRegistry.activePayoutToken();\n        uint8 decimals = IERC20Metadata(payoutToken).decimals();\n        if (decimals > 24) revert InvalidDecimals();\n\n        // Calculate limit in USD WAD\n        uint256 limitInUsdWad = (highWatermark * userLimitBps) / BPS_DENOMINATOR;\n\n        // Get payout token price in USD WAD\n        uint256 payoutPriceWad = redemptionPriceRouter.getPrice(payoutToken);\n\n        // Convert USD limit to token amount\n        // tokens = (USD * 10^decimals) / price\n        return Math.mulDiv(limitInUsdWad, 10 ** decimals, payoutPriceWad);\n    }\n\n    /**\n     * @notice Check vault balance and emit warning if below threshold\n     */\n    function _checkVaultBalance(address payoutToken) private {\n        uint256 vaultBalance = IERC20(payoutToken).balanceOf(address(vault));\n        uint256 threshold = getVaultLowBalanceThreshold();\n        uint256 dailyLimit = _getDailyLimit();\n\n        if (vaultBalance < threshold) {\n            emit RefillNeeded(vaultBalance, threshold, dailyLimit);\n        }\n    }\n}\n","deployed_bytecode":"0x6080806040526004361015610012575f80fd5b5f905f3560e01c908163127c7d061461135a575080631b5f41c7146113195780631d86828d146112d857806324a9d853146112b75780632c6cda93146112275780632cb4b6b0146111a7578063320767151461118a578063378f9472146110ac5780633f4ba83a14611044578063401d5dd414611027578063442c18f314610e83578063478222c214610e5a57806355d9e32914610e345780635c9302c914610e175780635c975abb14610df557806364cec4d314610dcf5780636c9fa59e14610d8c5780637a9596b514610d695780637a9e5e4b14610cc25780638120b57914610ca55780638456cb5914610c4a5780638b28ac0e14610bd25780638e41da8814610bb55780638fb3603714610b5a57806390d6b45f14610b17578063a15f39e814610afd578063a591f97f14610a57578063b426b82514610400578063b4a7a187146103e2578063b4e70d421461039e578063b729b62214610383578063b82926c71461033f578063bcd07d95146102fb578063bf7e214f146102d5578063c8030e1c146102b7578063d5fecb1b1461028b578063f4ed2fc21461026d578063fa77fc13146102115763fbfa77cf146101cb575f80fd5b3461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b147168152f35b80fd5b503461020e578060031936011261020e5761022c3633611e10565b7f7b23f269ff0c9b887e52362e954958c9d6f622f77cf2467a092686dced2c56cf6040610257611f57565b600354908060035582519182526020820152a180f35b503461020e578060031936011261020e576020600654604051908152f35b503461020e57602036600319011261020e5760206102af6102aa61137d565b611c5f565b604051908152f35b503461020e578060031936011261020e576020600b54604051908152f35b503461020e578060031936011261020e576001600160a01b036020915416604051908152f35b503461020e578060031936011261020e5760206040516001600160a01b037f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc3168152f35b503461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000009ea38e09f41a9de53972a68268ba0dcc6d2fadf8168152f35b503461020e578060031936011261020e5760206102af6118eb565b503461020e578060031936011261020e5760206040516001600160a01b037f000000000000000000000000fe76cf5ed606593fb7764f33627b8d7e0f9fab66168152f35b503461020e578060031936011261020e576020600954604051908152f35b50346108135760603660031901126108135761041a61137d565b602435906104283633611e10565b600260015414610a4857600260015561043f6121e0565b8115610a3957604051916373bed91960e11b83526001600160a01b038216928360048201526020816024816001600160a01b037f00000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b123995165afa908115610943575f91610a0a575b50156109fb576104b26121fb565b60405163491beb9560e01b8152916020836004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa928315610943575f936109ca575b5061050b838361193a565b939060065481106109bb57600754106109ac57600b5461052b8582611416565b610533611ae6565b1061099d5761054183611c5f565b9061054c8683611416565b610554611d36565b1061098e578561056391611416565b600b55855f52600e6020528460405f20620151804204815481115f1461097857815560010155505b61271061059e61ffff6008541686611437565b04906105aa828661144a565b926044358410610969576040516323b872dd60e01b60208083019182526001600160a01b03848116602485015230604485015260648085018a905284527f0000000000000000000000005086bf358635b81d8c47c66d1c8b9e567db70c72169290915f916106196084826113a9565b519082855af115610943575f513d6109605750803b155b61094e57803b1561081357604051632770a7eb60e21b815230600482015260248101879052905f908290604490829084905af180156109435761092e575b50876001600160a01b037f0000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b1471691823b1561090057604051636ce5768960e11b81526001600160a01b03858116600483015291909116602482015260448101869052818160648183875af180156108f557610919575b50508261082a575b6001600160a01b0391602460209260405194859384926370a0823160e01b84526004840152165afa90811561081f5787916107c1575b50907f7c1adc87b2070531e3d3a04a7e8972115f3a5c4c2108523fdf8295bc4daa9f409460809493926107526118eb565b61075a611ae6565b91818110610783575b505050604051938452602084015260408301526060820152a26001805580f35b7fffe819fd21fcb93ace1b24ad7d33df4f0b7f681d5af8ec4990d53bb0a2cc8e039260609260405192835260208301526040820152a15f8080610763565b93929190506020843d602011610817575b816107df602093836113a9565b81010312610813579251919290917f7c1adc87b2070531e3d3a04a7e8972115f3a5c4c2108523fdf8295bc4daa9f40610721565b5f80fd5b3d91506107d2565b6040513d89823e3d90fd5b876001600160a01b0360085460101c16823b1561090057604051636ce5768960e11b81526001600160a01b03858116600483015291909116602482015260448101859052818160648183875af180156108f557610904575b506001600160a01b0360085460101c16803b156109005760405163029b83f560e21b81526001600160a01b0385166004820152602481018690529082908290604490829084905af180156108f5576108dc575b50506106eb565b816108e6916113a9565b6108f157875f6108d5565b8780fd5b6040513d84823e3d90fd5b5080fd5b8161090e916113a9565b6108f157875f610882565b81610923916113a9565b6108f157875f6106e3565b61093b9198505f906113a9565b5f965f61066e565b6040513d5f823e3d90fd5b635274afe760e01b5f5260045260245ffd5b60011415610630565b63bb2875c360e01b5f5260045ffd5b509160019161098691611416565b91015561058b565b6361eea57560e11b5f5260045ffd5b638fe2651160e01b5f5260045ffd5b631493202160e11b5f5260045ffd5b63860b82a960e01b5f5260045ffd5b6109ed91935060203d6020116109f4575b6109e581836113a9565b8101906113f7565b915f610500565b503d6109db565b6320e155c960e21b5f5260045ffd5b610a2c915060203d602011610a32575b610a2481836113a9565b8101906113df565b5f6104a4565b503d610a1a565b63162908e360e11b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b3461081357602036600319011261081357610a7061137d565b610a7a3633611e10565b6001600160a01b038116908115610aee5775ffffffffffffffffffffffffffffffffffffffff00006008549160101b169075ffffffffffffffffffffffffffffffffffffffff00001916176008557f6e5cd85c798e1d300d3f0caf1f7d1f862360d2edbb2bc2034caa0196c1220afe5f80a2005b63d92e233d60e01b5f5260045ffd5b34610813575f3660031901126108135760206102af6117db565b34610813575f3660031901126108135760206040516001600160a01b037f00000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b123995168152f35b34610813575f366003190112610813575f5460a01c60ff1615610bad576020638fb3603760e01b5b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152f35b60205f610b82565b34610813575f366003190112610813576020600554604051908152f35b3461081357610be036611393565b610bea3633611e10565b81158015610c40575b610c3157816040917f6281a49f525db40b72d3ca6b6c63c603aee9e340ef02cd31b4185a0039bc4ca5936006558060075582519182526020820152a1005b63c52a9bd360e01b5f5260045ffd5b5081811115610bf3565b34610813575f36600319011261081357610c643633611e10565b610c6c6121e0565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b34610813575f366003190112610813576020600354604051908152f35b3461081357602036600319011261081357610cdb61137d565b5f54906001600160a01b0382163303610d5757803b15610d3b577f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad916001600160a01b036020921680916001600160a01b031916175f55604051908152a1005b6001600160a01b03906361798f2f60e11b5f521660045260245ffd5b62d1953b60e31b5f523360045260245ffd5b346108135760203660031901126108135760206102af610d8761137d565b6117af565b34610813575f3660031901126108135760206040516001600160a01b037f0000000000000000000000005086bf358635b81d8c47c66d1c8b9e567db70c72168152f35b34610813575f366003190112610813576040610de96116e7565b82519182526020820152f35b34610813575f36600319011261081357602060ff600254166040519015158152f35b34610813575f366003190112610813576020600a54604051908152f35b34610813575f3660031901126108135760206001600160a01b03600d5416604051908152f35b34610813575f3660031901126108135760206001600160a01b0360085460101c16604051908152f35b34610813575f3660031901126108135760405163491beb9560e01b81526020816004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa8015610943576001600160a01b03915f91611008575b506040516370a0823160e01b81527f0000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b1476001600160a01b031660048201529116602082602481845afa918215610943575f92610fd3575b506020602491604051928380926370a0823160e01b82526001600160a01b037f0000000000000000000000009ea38e09f41a9de53972a68268ba0dcc6d2fadf81660048301525afa908115610943575f91610fa0575b60206102af8385611416565b90506020813d602011610fcb575b81610fbb602093836113a9565b8101031261081357516020610f94565b3d9150610fae565b9091506020813d602011611000575b81610fef602093836113a9565b810103126108135751906020610f3e565b3d9150610fe2565b611021915060203d6020116109f4576109e581836113a9565b82610ee8565b34610813575f366003190112610813576020600454604051908152f35b34610813575f3660031901126108135761105e3633611e10565b60025460ff81161561109d5760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34610813576020366003190112610813576110c561137d565b604051906373bed91960e11b82526001600160a01b03811660048301526020826024816001600160a01b037f00000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b123995165afa9081156109435760c0925f92611169575b506111376111316117db565b916117af565b6006546007549161ffff60085416936040519515158652602086015260408501526060840152608083015260a0820152f35b61118391925060203d602011610a3257610a2481836113a9565b9083611125565b34610813575f366003190112610813576020600754604051908152f35b34610813576111b536611393565b6111bf3633611e10565b8115801561121c575b610c315780158015611213575b610c3157816040917f4d4981437d0211f9e6843eb024d9ada1fa3a99514d4343d4aece106dd11524bb936004558060055582519182526020820152a1005b508181116111d5565b5061271082116111c8565b346108135760203660031901126108135760043561ffff8116809103610813576112513633611e10565b6103e88111610c3157801515806112a1575b610aee576020817fc8fcf8ee1425e7e60b8af83735e1eb516d5b9ef05bfd6eece552ebaeb7c75b489261ffff196008541617600855604051908152a1005b506001600160a01b0360085460101c1615611263565b34610813575f36600319011261081357602061ffff60085416604051908152f35b34610813576020366003190112610813576001600160a01b036112f961137d565b165f52600e6020526040805f206001815491015482519182526020820152f35b3461081357604036600319011261081357608061134061133761137d565b60243590611457565b916040519384526020840152604083015215156060820152f35b34610813575f366003190112610813576020906001600160a01b03600c54168152f35b600435906001600160a01b038216820361081357565b6040906003190112610813576004359060243590565b90601f8019910116810190811067ffffffffffffffff8211176113cb57604052565b634e487b7160e01b5f52604160045260245ffd5b90816020910312610813575180151581036108135790565b9081602091031261081357516001600160a01b03811681036108135790565b9190820180921161142357565b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561142357565b9190820391821161142357565b81158015611664575b6115525760405163491beb9560e01b81527f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b031692602082600481875afa908115610943576114bd925f92611643575b5061193a565b92906006548110908115611637575b5061162a57600a546201518042041190811561156a575b501561155e576114f3825f611416565b6114fb611ae6565b10611552578161150d61151292611c5f565b611416565b61151a611d36565b106115475761271061153261ffff6008541683611437565b049161153e838361144a565b91929190600190565b505f905f905f905f90565b50505f905f905f905f90565b6114f382600b54611416565b60405163491beb9560e01b8152909150602081600481855afa8015610943576001600160a01b03915f9161160b575b5016151590816115ab575b505f6114e3565b60405163491beb9560e01b81529150602090829060049082905afa908115610943575f916115ec575b506001600160a01b0380600c5416911614155f6115a4565b611605915060203d6020116109f4576109e581836113a9565b5f6115d4565b611624915060203d6020116109f4576109e581836113a9565b5f611599565b5050505f905f905f905f90565b9050600754105f6114cc565b61165d91925060203d6020116109f4576109e581836113a9565b905f6114b7565b506040516373bed91960e11b81526001600160a01b03821660048201526020816024816001600160a01b037f00000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b123995165afa908115610943575f916116c8575b5015611460565b6116e1915060203d602011610a3257610a2481836113a9565b5f6116c1565b60405163491beb9560e01b8152906201518042046020836004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa928315610943575f9361178e575b50600a549283821190811561175d575b506117575750600b5490565b91505f90565b6001600160a01b0316801515915081611778575b505f61174b565b90506001600160a01b03600c541614155f611771565b6117a891935060203d6020116109f4576109e581836113a9565b915f61173b565b6117b890611c5f565b6117c0611d36565b90808211156117d5576117d29161144a565b90565b50505f90565b600a54620151804204118015611803575b156117fb575f5b6117c0611ae6565b600b546117f3565b5060405163491beb9560e01b81527f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b031690602081600481855afa8015610943576001600160a01b03915f916118cc575b50161515908161186c575b506117ec565b60405163491beb9560e01b81529150602090829060049082905afa908115610943575f916118ad575b506001600160a01b0380600c5416911614155f611866565b6118c6915060203d6020116109f4576109e581836113a9565b5f611895565b6118e5915060203d6020116109f4576109e581836113a9565b5f61185b565b6118f3611ae6565b6109c48102908082046109c4149015171561142357612710900490565b90816020910312610813575160ff811681036108135790565b60ff16604d811161142357600a0a90565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000005086bf358635b81d8c47c66d1c8b9e567db70c72811660048301527f000000000000000000000000fe76cf5ed606593fb7764f33627b8d7e0f9fab66169392602082602481885afa918215610943575f92611ab1575b509060206001600160a01b03926024604051809581936341976e0960e01b835216988960048301525afa918215610943575f92611a79575b506119f9602091600494612097565b946040519384809263313ce56760e01b82525afa918215610943575f92611a48575b50601860ff831611611a3957611a336117d292611929565b8461212d565b630692acc560e51b5f5260045ffd5b611a6b91925060203d602011611a72575b611a6381836113a9565b810190611910565b905f611a1b565b503d611a59565b9291506020833d602011611aa9575b81611a95602093836113a9565b8101031261081357915190916119f96119ea565b3d9150611a88565b91506020823d602011611ade575b81611acc602093836113a9565b810103126108135790519060206119b2565b3d9150611abf565b60405163491beb9560e01b81526020816004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa8015610943576001600160a01b03915f91611c40575b5060405163313ce56760e01b81529116602082600481845afa918215610943575f92611c1f575b50601860ff831611611a3957612710611b8060035460045490611437565b04604051916341976e0960e01b835260048301526020826024816001600160a01b037f000000000000000000000000fe76cf5ed606593fb7764f33627b8d7e0f9fab66165afa918215610943575f92611be7575b50611be16117d293611929565b9061212d565b9291506020833d602011611c17575b81611c03602093836113a9565b810103126108135791519091611be1611bd4565b3d9150611bf6565b611c3991925060203d602011611a7257611a6381836113a9565b905f611b62565b611c59915060203d6020116109f4576109e581836113a9565b5f611b3b565b6001600160a01b03165f52600e60205260405f206201518042046040519063491beb9560e01b82526020826004816001600160a01b037f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc3165afa918215610943575f92611d15575b50825410908115611ce4575b50611cdf576001015490565b505f90565b6001600160a01b0316801515915081611cff575b505f611cd3565b90506001600160a01b03600c541614155f611cf8565b611d2f91925060203d6020116109f4576109e581836113a9565b905f611cc7565b60405163491beb9560e01b81526020816004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa8015610943576001600160a01b03915f91611df1575b5060405163313ce56760e01b81529116602082600481845afa918215610943575f92611dd0575b50601860ff831611611a3957612710611b8060035460055490611437565b611dea91925060203d602011611a7257611a6381836113a9565b905f611db2565b611e0a915060203d6020116109f4576109e581836113a9565b5f611d8b565b905f915f54916001600160a01b0383169281600411610813575f5f9060405f8151966001600160a01b03602089019163b700961360e01b8352169788602482015230604482015263ffffffff60e01b833516606482015260648152611e766084826113a9565b828052826020525190895afa611f44575b15611e95575b505050505050565b63ffffffff1615611f325760ff60a01b1916600160a01b175f55823b15610813576064925f9283604051958680958194634a63ebf760e11b83526004830152604060248301528060448301528084848401378181018301849052601f01601f191681010301925af1801561094357611f1f575b50805460ff60a01b191690555f8080808080611e8d565b611f2b91505f906113a9565b5f5f611f08565b8262d1953b60e31b5f5260045260245ffd5b50505f516020518060201c150290611e87565b60405163491beb9560e01b81526020816004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa8015610943576001600160a01b03915f91612078575b50161561207457604460206001600160a01b03600d54166040519283809263bd2111ad60e01b82526001600160a01b037f0000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b1471660048301526001600160a01b037f0000000000000000000000009ea38e09f41a9de53972a68268ba0dcc6d2fadf81660248301525afa908115610943575f91612045575090565b90506020813d60201161206c575b81612060602093836113a9565b81010312610813575190565b3d9150612053565b5f90565b612091915060203d6020116109f4576109e581836113a9565b5f611fac565b9091905f905f19848209908481029283808410930392808403931461211a5782670de0b6b3a7640000111561210857507faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106699394670de0b6b3a7640000910990828211900360ee1b910360121c170290565b634e487b71905260116020526024601cfd5b505050670de0b6b3a76400009192500490565b90915f1983830992808302928380861095039480860395146121be57848311156121a65790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050915081156121cc570490565b634e487b7160e01b5f52601260045260245ffd5b60ff600254166121ec57565b63d93c066560e01b5f5260045ffd5b60095460405163491beb9560e01b8152620151804281900492046020826004817f000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc36001600160a01b03165afa918215610943575f9261239a575b5082118015612390575b6122e8576001600160a01b03829116801515806122d3575b61228f575b5050600a54811161228a5750565b600a55565b6001600160a01b03600c54828219821617600c555f600b55167fbb11959444d47d604029dd62fd382a3995b43cd24c3df72a28e6bfb1b3393ffd5f80a4805f61227c565b506001600160a01b03600c5416811415612277565b7fc8dcc76ff740e8e6f86ae858c5fb3922c058690822a48b92c2f26b7e8655f209916001600160a01b0360409261231d611f57565b92600354808511612357575b5042600955600a55166001600160a01b0319600c541617600c555f600b5560035482519182526020820152a1565b857f7b23f269ff0c9b887e52362e954958c9d6f622f77cf2467a092686dced2c56cf91866003558151908152866020820152a15f612329565b506003541561225f565b6123b491925060203d6020116109f4576109e581836113a9565b905f61225556fea2646970667358221220ccc675c88492725312adf14762558a68676528a6767b593286751c79651bf77464736f6c634300081e0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":500},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["@chainlink/=smart-contracts-public/lib/chainlink/","@openzeppelin/contracts/=smart-contracts-public/lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts-upgradeable/=smart-contracts-public/lib/openzeppelin-contracts-upgradeable/contracts/","forge-std/=smart-contracts-public/lib/forge-std/src/","openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/","chainlink/=smart-contracts-public/lib/chainlink/","erc4626-tests/=smart-contracts-public/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","halmos-cheatcodes/=smart-contracts-public/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=smart-contracts-public/lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=smart-contracts-public/lib/openzeppelin-contracts/"],"viaIR":true},"optimization_runs":500,"sourcify_repo_url":null,"decoded_constructor_args":[["0x3f0DA1C363e34802C6f12F9C27276dC0e6696FD8",{"internalType":"address","name":"_accessManager","type":"address"}],["0x5086bf358635B81D8C47C66d1C8b9E567Db70c72",{"internalType":"address","name":"_shareToken","type":"address"}],["0x5C454f5526e41fBE917b63475CD8CA7E4631B147",{"internalType":"address","name":"_vault","type":"address"}],["0xf788624278Dc0D5b4e494F834932e6938AA2Bdc3",{"internalType":"address","name":"_tokenRegistry","type":"address"}],["0xFe76cF5eD606593fB7764f33627B8D7E0f9Fab66",{"internalType":"address","name":"_priceRouter","type":"address"}],["0x82F1806AEab5Ecb9a485eb041d5Ed4940b123995",{"internalType":"address","name":"_kyc","type":"address"}],["0x9eA38e09F41A9DE53972a68268BA0Dcc6d2fAdf8",{"internalType":"address","name":"_custodialWallet","type":"address"}],["0x7E499842E7634cce793FFD5D44383BB4a2F086e0",{"internalType":"address","name":"_redemptionReserves","type":"address"}]],"compiler_version":"v0.8.30+commit.73712a01","is_verified_via_verifier_alliance":false,"verified_at":"2026-03-22T16:57:16.329439Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x61014080604052346103735761010081612920803803809161002182856103e5565b833981010312610373576100348161041c565b6100406020830161041c565b9061004d6040840161041c565b9161005a6060850161041c565b936100676080820161041c565b9261007460a0830161041c565b927f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad60206100b060e06100a960c0880161041c565b960161041c565b5f80546001600160a01b0319166001600160a01b03909616958617905560405194855293a1600180556107d06004556103e8600555678ac7230489e8000060065569d3c21bcecceda10000006007556001600160a01b03169485156103d6576001600160a01b03169586156103d6576001600160a01b03169384156103d6576001600160a01b03169283156103d6576001600160a01b03169081156103d6576001600160a01b038316156103d6576001600160a01b03169283156103d65760405163313ce56760e01b81526020816004818a5afa90811561037f575f91610399575b5060ff601291160361038a5760049660209660805260a0528460c05260e05261010052610120524260095560018060a01b0319600d541617600d55620151804204600a556040519283809263491beb9560e01b82525afa90811561037f575f91610341575b50600c80546001600160a01b0319166001600160a01b0392909216919091179055610220610430565b80610307575b6040516123f1908161052f82396080518181816105e901528181610dab0152611951015260a0518181816101ea0152818161067a01528181610ef80152611fde015260c05181818161031b015281816104c801528181610ea801528181611473015281816117030152818161181301528181611afb01528181611c9701528181611d4b01528181611f6c015261221d015260e0518181816103be015281816119790152611ba401526101005181818161047401528181610b36015281816110f2015261169101526101205181818161035f01528181610f5f015261200d0152f35b6040817f7b23f269ff0c9b887e52362e954958c9d6f622f77cf2467a092686dced2c56cf926003558151905f82526020820152a15f610226565b90506020813d602011610377575b8161035c602093836103e5565b810103126103735761036d9061041c565b5f6101f7565b5f80fd5b3d915061034f565b6040513d5f823e3d90fd5b630692acc560e51b5f5260045ffd5b90506020813d6020116103ce575b816103b4602093836103e5565b81010312610373575160ff811681036103735760ff610192565b3d91506103a7565b63d92e233d60e01b5f5260045ffd5b601f909101601f19168101906001600160401b0382119082101761040857604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361037357565b60c05160405163491beb9560e01b815290602090829060049082906001600160a01b03165afa90811561037f575f916104f4575b506001600160a01b0316156104f057600d5460a0516101205160405163bd2111ad60e01b81526001600160a01b03928316600482015290821660248201529160209183916044918391165afa90811561037f575f916104c1575090565b90506020813d6020116104e8575b816104dc602093836103e5565b81010312610373575190565b3d91506104cf565b5f90565b90506020813d602011610526575b8161050f602093836103e5565b81010312610373576105209061041c565b5f610464565b3d915061050256fe6080806040526004361015610012575f80fd5b5f905f3560e01c908163127c7d061461135a575080631b5f41c7146113195780631d86828d146112d857806324a9d853146112b75780632c6cda93146112275780632cb4b6b0146111a7578063320767151461118a578063378f9472146110ac5780633f4ba83a14611044578063401d5dd414611027578063442c18f314610e83578063478222c214610e5a57806355d9e32914610e345780635c9302c914610e175780635c975abb14610df557806364cec4d314610dcf5780636c9fa59e14610d8c5780637a9596b514610d695780637a9e5e4b14610cc25780638120b57914610ca55780638456cb5914610c4a5780638b28ac0e14610bd25780638e41da8814610bb55780638fb3603714610b5a57806390d6b45f14610b17578063a15f39e814610afd578063a591f97f14610a57578063b426b82514610400578063b4a7a187146103e2578063b4e70d421461039e578063b729b62214610383578063b82926c71461033f578063bcd07d95146102fb578063bf7e214f146102d5578063c8030e1c146102b7578063d5fecb1b1461028b578063f4ed2fc21461026d578063fa77fc13146102115763fbfa77cf146101cb575f80fd5b3461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b503461020e578060031936011261020e5761022c3633611e10565b7f7b23f269ff0c9b887e52362e954958c9d6f622f77cf2467a092686dced2c56cf6040610257611f57565b600354908060035582519182526020820152a180f35b503461020e578060031936011261020e576020600654604051908152f35b503461020e57602036600319011261020e5760206102af6102aa61137d565b611c5f565b604051908152f35b503461020e578060031936011261020e576020600b54604051908152f35b503461020e578060031936011261020e576001600160a01b036020915416604051908152f35b503461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020e578060031936011261020e5760206102af6118eb565b503461020e578060031936011261020e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020e578060031936011261020e576020600954604051908152f35b50346108135760603660031901126108135761041a61137d565b602435906104283633611e10565b600260015414610a4857600260015561043f6121e0565b8115610a3957604051916373bed91960e11b83526001600160a01b038216928360048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610943575f91610a0a575b50156109fb576104b26121fb565b60405163491beb9560e01b8152916020836004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa928315610943575f936109ca575b5061050b838361193a565b939060065481106109bb57600754106109ac57600b5461052b8582611416565b610533611ae6565b1061099d5761054183611c5f565b9061054c8683611416565b610554611d36565b1061098e578561056391611416565b600b55855f52600e6020528460405f20620151804204815481115f1461097857815560010155505b61271061059e61ffff6008541686611437565b04906105aa828661144a565b926044358410610969576040516323b872dd60e01b60208083019182526001600160a01b03848116602485015230604485015260648085018a905284527f0000000000000000000000000000000000000000000000000000000000000000169290915f916106196084826113a9565b519082855af115610943575f513d6109605750803b155b61094e57803b1561081357604051632770a7eb60e21b815230600482015260248101879052905f908290604490829084905af180156109435761092e575b50876001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691823b1561090057604051636ce5768960e11b81526001600160a01b03858116600483015291909116602482015260448101869052818160648183875af180156108f557610919575b50508261082a575b6001600160a01b0391602460209260405194859384926370a0823160e01b84526004840152165afa90811561081f5787916107c1575b50907f7c1adc87b2070531e3d3a04a7e8972115f3a5c4c2108523fdf8295bc4daa9f409460809493926107526118eb565b61075a611ae6565b91818110610783575b505050604051938452602084015260408301526060820152a26001805580f35b7fffe819fd21fcb93ace1b24ad7d33df4f0b7f681d5af8ec4990d53bb0a2cc8e039260609260405192835260208301526040820152a15f8080610763565b93929190506020843d602011610817575b816107df602093836113a9565b81010312610813579251919290917f7c1adc87b2070531e3d3a04a7e8972115f3a5c4c2108523fdf8295bc4daa9f40610721565b5f80fd5b3d91506107d2565b6040513d89823e3d90fd5b876001600160a01b0360085460101c16823b1561090057604051636ce5768960e11b81526001600160a01b03858116600483015291909116602482015260448101859052818160648183875af180156108f557610904575b506001600160a01b0360085460101c16803b156109005760405163029b83f560e21b81526001600160a01b0385166004820152602481018690529082908290604490829084905af180156108f5576108dc575b50506106eb565b816108e6916113a9565b6108f157875f6108d5565b8780fd5b6040513d84823e3d90fd5b5080fd5b8161090e916113a9565b6108f157875f610882565b81610923916113a9565b6108f157875f6106e3565b61093b9198505f906113a9565b5f965f61066e565b6040513d5f823e3d90fd5b635274afe760e01b5f5260045260245ffd5b60011415610630565b63bb2875c360e01b5f5260045ffd5b509160019161098691611416565b91015561058b565b6361eea57560e11b5f5260045ffd5b638fe2651160e01b5f5260045ffd5b631493202160e11b5f5260045ffd5b63860b82a960e01b5f5260045ffd5b6109ed91935060203d6020116109f4575b6109e581836113a9565b8101906113f7565b915f610500565b503d6109db565b6320e155c960e21b5f5260045ffd5b610a2c915060203d602011610a32575b610a2481836113a9565b8101906113df565b5f6104a4565b503d610a1a565b63162908e360e11b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b3461081357602036600319011261081357610a7061137d565b610a7a3633611e10565b6001600160a01b038116908115610aee5775ffffffffffffffffffffffffffffffffffffffff00006008549160101b169075ffffffffffffffffffffffffffffffffffffffff00001916176008557f6e5cd85c798e1d300d3f0caf1f7d1f862360d2edbb2bc2034caa0196c1220afe5f80a2005b63d92e233d60e01b5f5260045ffd5b34610813575f3660031901126108135760206102af6117db565b34610813575f3660031901126108135760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610813575f366003190112610813575f5460a01c60ff1615610bad576020638fb3603760e01b5b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152f35b60205f610b82565b34610813575f366003190112610813576020600554604051908152f35b3461081357610be036611393565b610bea3633611e10565b81158015610c40575b610c3157816040917f6281a49f525db40b72d3ca6b6c63c603aee9e340ef02cd31b4185a0039bc4ca5936006558060075582519182526020820152a1005b63c52a9bd360e01b5f5260045ffd5b5081811115610bf3565b34610813575f36600319011261081357610c643633611e10565b610c6c6121e0565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b34610813575f366003190112610813576020600354604051908152f35b3461081357602036600319011261081357610cdb61137d565b5f54906001600160a01b0382163303610d5757803b15610d3b577f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad916001600160a01b036020921680916001600160a01b031916175f55604051908152a1005b6001600160a01b03906361798f2f60e11b5f521660045260245ffd5b62d1953b60e31b5f523360045260245ffd5b346108135760203660031901126108135760206102af610d8761137d565b6117af565b34610813575f3660031901126108135760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610813575f366003190112610813576040610de96116e7565b82519182526020820152f35b34610813575f36600319011261081357602060ff600254166040519015158152f35b34610813575f366003190112610813576020600a54604051908152f35b34610813575f3660031901126108135760206001600160a01b03600d5416604051908152f35b34610813575f3660031901126108135760206001600160a01b0360085460101c16604051908152f35b34610813575f3660031901126108135760405163491beb9560e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610943576001600160a01b03915f91611008575b506040516370a0823160e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048201529116602082602481845afa918215610943575f92610fd3575b506020602491604051928380926370a0823160e01b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048301525afa908115610943575f91610fa0575b60206102af8385611416565b90506020813d602011610fcb575b81610fbb602093836113a9565b8101031261081357516020610f94565b3d9150610fae565b9091506020813d602011611000575b81610fef602093836113a9565b810103126108135751906020610f3e565b3d9150610fe2565b611021915060203d6020116109f4576109e581836113a9565b82610ee8565b34610813575f366003190112610813576020600454604051908152f35b34610813575f3660031901126108135761105e3633611e10565b60025460ff81161561109d5760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34610813576020366003190112610813576110c561137d565b604051906373bed91960e11b82526001600160a01b03811660048301526020826024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156109435760c0925f92611169575b506111376111316117db565b916117af565b6006546007549161ffff60085416936040519515158652602086015260408501526060840152608083015260a0820152f35b61118391925060203d602011610a3257610a2481836113a9565b9083611125565b34610813575f366003190112610813576020600754604051908152f35b34610813576111b536611393565b6111bf3633611e10565b8115801561121c575b610c315780158015611213575b610c3157816040917f4d4981437d0211f9e6843eb024d9ada1fa3a99514d4343d4aece106dd11524bb936004558060055582519182526020820152a1005b508181116111d5565b5061271082116111c8565b346108135760203660031901126108135760043561ffff8116809103610813576112513633611e10565b6103e88111610c3157801515806112a1575b610aee576020817fc8fcf8ee1425e7e60b8af83735e1eb516d5b9ef05bfd6eece552ebaeb7c75b489261ffff196008541617600855604051908152a1005b506001600160a01b0360085460101c1615611263565b34610813575f36600319011261081357602061ffff60085416604051908152f35b34610813576020366003190112610813576001600160a01b036112f961137d565b165f52600e6020526040805f206001815491015482519182526020820152f35b3461081357604036600319011261081357608061134061133761137d565b60243590611457565b916040519384526020840152604083015215156060820152f35b34610813575f366003190112610813576020906001600160a01b03600c54168152f35b600435906001600160a01b038216820361081357565b6040906003190112610813576004359060243590565b90601f8019910116810190811067ffffffffffffffff8211176113cb57604052565b634e487b7160e01b5f52604160045260245ffd5b90816020910312610813575180151581036108135790565b9081602091031261081357516001600160a01b03811681036108135790565b9190820180921161142357565b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561142357565b9190820391821161142357565b81158015611664575b6115525760405163491beb9560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692602082600481875afa908115610943576114bd925f92611643575b5061193a565b92906006548110908115611637575b5061162a57600a546201518042041190811561156a575b501561155e576114f3825f611416565b6114fb611ae6565b10611552578161150d61151292611c5f565b611416565b61151a611d36565b106115475761271061153261ffff6008541683611437565b049161153e838361144a565b91929190600190565b505f905f905f905f90565b50505f905f905f905f90565b6114f382600b54611416565b60405163491beb9560e01b8152909150602081600481855afa8015610943576001600160a01b03915f9161160b575b5016151590816115ab575b505f6114e3565b60405163491beb9560e01b81529150602090829060049082905afa908115610943575f916115ec575b506001600160a01b0380600c5416911614155f6115a4565b611605915060203d6020116109f4576109e581836113a9565b5f6115d4565b611624915060203d6020116109f4576109e581836113a9565b5f611599565b5050505f905f905f905f90565b9050600754105f6114cc565b61165d91925060203d6020116109f4576109e581836113a9565b905f6114b7565b506040516373bed91960e11b81526001600160a01b03821660048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115610943575f916116c8575b5015611460565b6116e1915060203d602011610a3257610a2481836113a9565b5f6116c1565b60405163491beb9560e01b8152906201518042046020836004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa928315610943575f9361178e575b50600a549283821190811561175d575b506117575750600b5490565b91505f90565b6001600160a01b0316801515915081611778575b505f61174b565b90506001600160a01b03600c541614155f611771565b6117a891935060203d6020116109f4576109e581836113a9565b915f61173b565b6117b890611c5f565b6117c0611d36565b90808211156117d5576117d29161144a565b90565b50505f90565b600a54620151804204118015611803575b156117fb575f5b6117c0611ae6565b600b546117f3565b5060405163491beb9560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa8015610943576001600160a01b03915f916118cc575b50161515908161186c575b506117ec565b60405163491beb9560e01b81529150602090829060049082905afa908115610943575f916118ad575b506001600160a01b0380600c5416911614155f611866565b6118c6915060203d6020116109f4576109e581836113a9565b5f611895565b6118e5915060203d6020116109f4576109e581836113a9565b5f61185b565b6118f3611ae6565b6109c48102908082046109c4149015171561142357612710900490565b90816020910312610813575160ff811681036108135790565b60ff16604d811161142357600a0a90565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169392602082602481885afa918215610943575f92611ab1575b509060206001600160a01b03926024604051809581936341976e0960e01b835216988960048301525afa918215610943575f92611a79575b506119f9602091600494612097565b946040519384809263313ce56760e01b82525afa918215610943575f92611a48575b50601860ff831611611a3957611a336117d292611929565b8461212d565b630692acc560e51b5f5260045ffd5b611a6b91925060203d602011611a72575b611a6381836113a9565b810190611910565b905f611a1b565b503d611a59565b9291506020833d602011611aa9575b81611a95602093836113a9565b8101031261081357915190916119f96119ea565b3d9150611a88565b91506020823d602011611ade575b81611acc602093836113a9565b810103126108135790519060206119b2565b3d9150611abf565b60405163491beb9560e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610943576001600160a01b03915f91611c40575b5060405163313ce56760e01b81529116602082600481845afa918215610943575f92611c1f575b50601860ff831611611a3957612710611b8060035460045490611437565b04604051916341976e0960e01b835260048301526020826024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa918215610943575f92611be7575b50611be16117d293611929565b9061212d565b9291506020833d602011611c17575b81611c03602093836113a9565b810103126108135791519091611be1611bd4565b3d9150611bf6565b611c3991925060203d602011611a7257611a6381836113a9565b905f611b62565b611c59915060203d6020116109f4576109e581836113a9565b5f611b3b565b6001600160a01b03165f52600e60205260405f206201518042046040519063491beb9560e01b82526020826004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa918215610943575f92611d15575b50825410908115611ce4575b50611cdf576001015490565b505f90565b6001600160a01b0316801515915081611cff575b505f611cd3565b90506001600160a01b03600c541614155f611cf8565b611d2f91925060203d6020116109f4576109e581836113a9565b905f611cc7565b60405163491beb9560e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610943576001600160a01b03915f91611df1575b5060405163313ce56760e01b81529116602082600481845afa918215610943575f92611dd0575b50601860ff831611611a3957612710611b8060035460055490611437565b611dea91925060203d602011611a7257611a6381836113a9565b905f611db2565b611e0a915060203d6020116109f4576109e581836113a9565b5f611d8b565b905f915f54916001600160a01b0383169281600411610813575f5f9060405f8151966001600160a01b03602089019163b700961360e01b8352169788602482015230604482015263ffffffff60e01b833516606482015260648152611e766084826113a9565b828052826020525190895afa611f44575b15611e95575b505050505050565b63ffffffff1615611f325760ff60a01b1916600160a01b175f55823b15610813576064925f9283604051958680958194634a63ebf760e11b83526004830152604060248301528060448301528084848401378181018301849052601f01601f191681010301925af1801561094357611f1f575b50805460ff60a01b191690555f8080808080611e8d565b611f2b91505f906113a9565b5f5f611f08565b8262d1953b60e31b5f5260045260245ffd5b50505f516020518060201c150290611e87565b60405163491beb9560e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610943576001600160a01b03915f91612078575b50161561207457604460206001600160a01b03600d54166040519283809263bd2111ad60e01b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048301526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248301525afa908115610943575f91612045575090565b90506020813d60201161206c575b81612060602093836113a9565b81010312610813575190565b3d9150612053565b5f90565b612091915060203d6020116109f4576109e581836113a9565b5f611fac565b9091905f905f19848209908481029283808410930392808403931461211a5782670de0b6b3a7640000111561210857507faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106699394670de0b6b3a7640000910990828211900360ee1b910360121c170290565b634e487b71905260116020526024601cfd5b505050670de0b6b3a76400009192500490565b90915f1983830992808302928380861095039480860395146121be57848311156121a65790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050915081156121cc570490565b634e487b7160e01b5f52601260045260245ffd5b60ff600254166121ec57565b63d93c066560e01b5f5260045ffd5b60095460405163491beb9560e01b8152620151804281900492046020826004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215610943575f9261239a575b5082118015612390575b6122e8576001600160a01b03829116801515806122d3575b61228f575b5050600a54811161228a5750565b600a55565b6001600160a01b03600c54828219821617600c555f600b55167fbb11959444d47d604029dd62fd382a3995b43cd24c3df72a28e6bfb1b3393ffd5f80a4805f61227c565b506001600160a01b03600c5416811415612277565b7fc8dcc76ff740e8e6f86ae858c5fb3922c058690822a48b92c2f26b7e8655f209916001600160a01b0360409261231d611f57565b92600354808511612357575b5042600955600a55166001600160a01b0319600c541617600c555f600b5560035482519182526020820152a1565b857f7b23f269ff0c9b887e52362e954958c9d6f622f77cf2467a092686dced2c56cf91866003558151908152866020820152a15f612329565b506003541561225f565b6123b491925060203d6020116109f4576109e581836113a9565b905f61225556fea2646970667358221220ccc675c88492725312adf14762558a68676528a6767b593286751c79651bf77464736f6c634300081e00330000000000000000000000003f0da1c363e34802c6f12f9c27276dc0e6696fd80000000000000000000000005086bf358635b81d8c47c66d1c8b9e567db70c720000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b147000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc3000000000000000000000000fe76cf5ed606593fb7764f33627b8d7e0f9fab6600000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b1239950000000000000000000000009ea38e09f41a9de53972a68268ba0dcc6d2fadf80000000000000000000000007e499842e7634cce793ffd5d44383bb4a2f086e0","name":"InstantRedemption","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/access/manager/AccessManaged.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/AccessManaged.sol)\n\npragma solidity ^0.8.20;\n\nimport {AuthorityUtils} from \"./AuthorityUtils.sol\";\nimport {IAccessManager} from \"./IAccessManager.sol\";\nimport {IAccessManaged} from \"./IAccessManaged.sol\";\nimport {Context} from \"../../utils/Context.sol\";\n\n/**\n * @dev This contract module makes available a {restricted} modifier. Functions decorated with this modifier will be\n * permissioned according to an \"authority\": a contract like {AccessManager} that follows the {IAuthority} interface,\n * implementing a policy that allows certain callers to access certain functions.\n *\n * IMPORTANT: The `restricted` modifier should never be used on `internal` functions, judiciously used in `public`\n * functions, and ideally only used in `external` functions. See {restricted}.\n */\nabstract contract AccessManaged is Context, IAccessManaged {\n    address private _authority;\n\n    bool private _consumingSchedule;\n\n    /**\n     * @dev Initializes the contract connected to an initial authority.\n     */\n    constructor(address initialAuthority) {\n        _setAuthority(initialAuthority);\n    }\n\n    /**\n     * @dev Restricts access to a function as defined by the connected Authority for this contract and the\n     * caller and selector of the function that entered the contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * In general, this modifier should only be used on `external` functions. It is okay to use it on `public`\n     * functions that are used as external entry points and are not called internally. Unless you know what you're\n     * doing, it should never be used on `internal` functions. Failure to follow these rules can have critical security\n     * implications! This is because the permissions are determined by the function that entered the contract, i.e. the\n     * function at the bottom of the call stack, and not the function where the modifier is visible in the source code.\n     * ====\n     *\n     * [WARNING]\n     * ====\n     * Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`]\n     * function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These\n     * functions are the only execution paths where a function selector cannot be unambiguously determined from the calldata\n     * since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function\n     * if no calldata is provided. (See {_checkCanCall}).\n     *\n     * The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length.\n     * ====\n     */\n    modifier restricted() {\n        _checkCanCall(_msgSender(), _msgData());\n        _;\n    }\n\n    /// @inheritdoc IAccessManaged\n    function authority() public view virtual returns (address) {\n        return _authority;\n    }\n\n    /// @inheritdoc IAccessManaged\n    function setAuthority(address newAuthority) public virtual {\n        address caller = _msgSender();\n        if (caller != authority()) {\n            revert AccessManagedUnauthorized(caller);\n        }\n        if (newAuthority.code.length == 0) {\n            revert AccessManagedInvalidAuthority(newAuthority);\n        }\n        _setAuthority(newAuthority);\n    }\n\n    /// @inheritdoc IAccessManaged\n    function isConsumingScheduledOp() public view returns (bytes4) {\n        return _consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0);\n    }\n\n    /**\n     * @dev Transfers control to a new authority. Internal function with no access restriction. Allows bypassing the\n     * permissions set by the current authority.\n     */\n    function _setAuthority(address newAuthority) internal virtual {\n        _authority = newAuthority;\n        emit AuthorityUpdated(newAuthority);\n    }\n\n    /**\n     * @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata\n     * is less than 4 bytes long.\n     */\n    function _checkCanCall(address caller, bytes calldata data) internal virtual {\n        (bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay(\n            authority(),\n            caller,\n            address(this),\n            bytes4(data[0:4])\n        );\n        if (!immediate) {\n            if (delay > 0) {\n                _consumingSchedule = true;\n                IAccessManager(authority()).consumeScheduledOp(caller, data);\n                _consumingSchedule = false;\n            } else {\n                revert AccessManagedUnauthorized(caller);\n            }\n        }\n    }\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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 Context {\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":"smart-contracts-public/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(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":"smart-contracts-public/lib/openzeppelin-contracts/contracts/access/manager/AuthorityUtils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (access/manager/AuthorityUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAuthority} from \"./IAuthority.sol\";\n\nlibrary AuthorityUtils {\n    /**\n     * @dev Since `AccessManager` implements an extended IAuthority interface, invoking `canCall` with backwards compatibility\n     * for the preexisting `IAuthority` interface requires special care to avoid reverting on insufficient return data.\n     * This helper function takes care of invoking `canCall` in a backwards compatible way without reverting.\n     */\n    function canCallWithDelay(\n        address authority,\n        address caller,\n        address target,\n        bytes4 selector\n    ) internal view returns (bool immediate, uint32 delay) {\n        bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector));\n\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x00)\n            mstore(0x20, 0x00)\n\n            if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) {\n                immediate := mload(0x00)\n                delay := mload(0x20)\n\n                // If delay does not fit in a uint32, return 0 (no delay)\n                // equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 }\n                delay := mul(delay, iszero(shr(32, delay)))\n            }\n        }\n    }\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/access/manager/IAccessManaged.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManaged.sol)\n\npragma solidity >=0.8.4;\n\ninterface IAccessManaged {\n    /**\n     * @dev Authority that manages this contract was updated.\n     */\n    event AuthorityUpdated(address authority);\n\n    error AccessManagedUnauthorized(address caller);\n    error AccessManagedRequiredDelay(address caller, uint32 delay);\n    error AccessManagedInvalidAuthority(address authority);\n\n    /**\n     * @dev Returns the current authority.\n     */\n    function authority() external view returns (address);\n\n    /**\n     * @dev Transfers control to a new authority. The caller must be the current authority.\n     */\n    function setAuthority(address) external;\n\n    /**\n     * @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is\n     * being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs\n     * attacker controlled calls.\n     */\n    function isConsumingScheduledOp() external view returns (bytes4);\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/access/manager/IAccessManager.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManager.sol)\n\npragma solidity >=0.8.4;\n\ninterface IAccessManager {\n    /**\n     * @dev A delayed operation was scheduled.\n     */\n    event OperationScheduled(\n        bytes32 indexed operationId,\n        uint32 indexed nonce,\n        uint48 schedule,\n        address caller,\n        address target,\n        bytes data\n    );\n\n    /**\n     * @dev A scheduled operation was executed.\n     */\n    event OperationExecuted(bytes32 indexed operationId, uint32 indexed nonce);\n\n    /**\n     * @dev A scheduled operation was canceled.\n     */\n    event OperationCanceled(bytes32 indexed operationId, uint32 indexed nonce);\n\n    /**\n     * @dev Informational labelling for a roleId.\n     */\n    event RoleLabel(uint64 indexed roleId, string label);\n\n    /**\n     * @dev Emitted when `account` is granted `roleId`.\n     *\n     * NOTE: The meaning of the `since` argument depends on the `newMember` argument.\n     * If the role is granted to a new member, the `since` argument indicates when the account becomes a member of the role,\n     * otherwise it indicates the execution delay for this account and roleId is updated.\n     */\n    event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, bool newMember);\n\n    /**\n     * @dev Emitted when `account` membership or `roleId` is revoked. Unlike granting, revoking is instantaneous.\n     */\n    event RoleRevoked(uint64 indexed roleId, address indexed account);\n\n    /**\n     * @dev Role acting as admin over a given `roleId` is updated.\n     */\n    event RoleAdminChanged(uint64 indexed roleId, uint64 indexed admin);\n\n    /**\n     * @dev Role acting as guardian over a given `roleId` is updated.\n     */\n    event RoleGuardianChanged(uint64 indexed roleId, uint64 indexed guardian);\n\n    /**\n     * @dev Grant delay for a given `roleId` will be updated to `delay` when `since` is reached.\n     */\n    event RoleGrantDelayChanged(uint64 indexed roleId, uint32 delay, uint48 since);\n\n    /**\n     * @dev Target mode is updated (true = closed, false = open).\n     */\n    event TargetClosed(address indexed target, bool closed);\n\n    /**\n     * @dev Role required to invoke `selector` on `target` is updated to `roleId`.\n     */\n    event TargetFunctionRoleUpdated(address indexed target, bytes4 selector, uint64 indexed roleId);\n\n    /**\n     * @dev Admin delay for a given `target` will be updated to `delay` when `since` is reached.\n     */\n    event TargetAdminDelayUpdated(address indexed target, uint32 delay, uint48 since);\n\n    error AccessManagerAlreadyScheduled(bytes32 operationId);\n    error AccessManagerNotScheduled(bytes32 operationId);\n    error AccessManagerNotReady(bytes32 operationId);\n    error AccessManagerExpired(bytes32 operationId);\n    error AccessManagerLockedRole(uint64 roleId);\n    error AccessManagerBadConfirmation();\n    error AccessManagerUnauthorizedAccount(address msgsender, uint64 roleId);\n    error AccessManagerUnauthorizedCall(address caller, address target, bytes4 selector);\n    error AccessManagerUnauthorizedConsume(address target);\n    error AccessManagerUnauthorizedCancel(address msgsender, address caller, address target, bytes4 selector);\n    error AccessManagerInvalidInitialAdmin(address initialAdmin);\n\n    /**\n     * @dev Check if an address (`caller`) is authorised to call a given function on a given contract directly (with\n     * no restriction). Additionally, it returns the delay needed to perform the call indirectly through the {schedule}\n     * & {execute} workflow.\n     *\n     * This function is usually called by the targeted contract to control immediate execution of restricted functions.\n     * Therefore we only return true if the call can be performed without any delay. If the call is subject to a\n     * previously set delay (not zero), then the function should return false and the caller should schedule the operation\n     * for future execution.\n     *\n     * If `allowed` is true, the delay can be disregarded and the operation can be immediately executed, otherwise\n     * the operation can be executed if and only if delay is greater than 0.\n     *\n     * NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that\n     * is backward compatible. Some contracts may thus ignore the second return argument. In that case they will fail\n     * to identify the indirect workflow, and will consider calls that require a delay to be forbidden.\n     *\n     * NOTE: This function does not report the permissions of the admin functions in the manager itself. These are defined by the\n     * {AccessManager} documentation.\n     */\n    function canCall(\n        address caller,\n        address target,\n        bytes4 selector\n    ) external view returns (bool allowed, uint32 delay);\n\n    /**\n     * @dev Expiration delay for scheduled proposals. Defaults to 1 week.\n     *\n     * IMPORTANT: Avoid overriding the expiration with 0. Otherwise every contract proposal will be expired immediately,\n     * disabling any scheduling usage.\n     */\n    function expiration() external view returns (uint32);\n\n    /**\n     * @dev Minimum setback for all delay updates, with the exception of execution delays. It\n     * can be increased without setback (and reset via {revokeRole} in the case event of an\n     * accidental increase). Defaults to 5 days.\n     */\n    function minSetback() external view returns (uint32);\n\n    /**\n     * @dev Get whether the contract is closed disabling any access. Otherwise role permissions are applied.\n     *\n     * NOTE: When the manager itself is closed, admin functions are still accessible to avoid locking the contract.\n     */\n    function isTargetClosed(address target) external view returns (bool);\n\n    /**\n     * @dev Get the role required to call a function.\n     */\n    function getTargetFunctionRole(address target, bytes4 selector) external view returns (uint64);\n\n    /**\n     * @dev Get the admin delay for a target contract. Changes to contract configuration are subject to this delay.\n     */\n    function getTargetAdminDelay(address target) external view returns (uint32);\n\n    /**\n     * @dev Get the id of the role that acts as an admin for the given role.\n     *\n     * The admin permission is required to grant the role, revoke the role and update the execution delay to execute\n     * an operation that is restricted to this role.\n     */\n    function getRoleAdmin(uint64 roleId) external view returns (uint64);\n\n    /**\n     * @dev Get the role that acts as a guardian for a given role.\n     *\n     * The guardian permission allows canceling operations that have been scheduled under the role.\n     */\n    function getRoleGuardian(uint64 roleId) external view returns (uint64);\n\n    /**\n     * @dev Get the role current grant delay.\n     *\n     * Its value may change at any point without an event emitted following a call to {setGrantDelay}.\n     * Changes to this value, including effect timepoint are notified in advance by the {RoleGrantDelayChanged} event.\n     */\n    function getRoleGrantDelay(uint64 roleId) external view returns (uint32);\n\n    /**\n     * @dev Get the access details for a given account for a given role. These details include the timepoint at which\n     * membership becomes active, and the delay applied to all operation by this user that requires this permission\n     * level.\n     *\n     * Returns:\n     * [0] Timestamp at which the account membership becomes valid. 0 means role is not granted.\n     * [1] Current execution delay for the account.\n     * [2] Pending execution delay for the account.\n     * [3] Timestamp at which the pending execution delay will become active. 0 means no delay update is scheduled.\n     */\n    function getAccess(\n        uint64 roleId,\n        address account\n    ) external view returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect);\n\n    /**\n     * @dev Check if a given account currently has the permission level corresponding to a given role. Note that this\n     * permission might be associated with an execution delay. {getAccess} can provide more details.\n     */\n    function hasRole(uint64 roleId, address account) external view returns (bool isMember, uint32 executionDelay);\n\n    /**\n     * @dev Give a label to a role, for improved role discoverability by UIs.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {RoleLabel} event.\n     */\n    function labelRole(uint64 roleId, string calldata label) external;\n\n    /**\n     * @dev Add `account` to `roleId`, or change its execution delay.\n     *\n     * This gives the account the authorization to call any function that is restricted to this role. An optional\n     * execution delay (in seconds) can be set. If that delay is non 0, the user is required to schedule any operation\n     * that is restricted to members of this role. The user will only be able to execute the operation after the delay has\n     * passed, before it has expired. During this period, admin and guardians can cancel the operation (see {cancel}).\n     *\n     * If the account has already been granted this role, the execution delay will be updated. This update is not\n     * immediate and follows the delay rules. For example, if a user currently has a delay of 3 hours, and this is\n     * called to reduce that delay to 1 hour, the new delay will take some time to take effect, enforcing that any\n     * operation executed in the 3 hours that follows this update was indeed scheduled before this update.\n     *\n     * Requirements:\n     *\n     * - the caller must be an admin for the role (see {getRoleAdmin})\n     * - granted role must not be the `PUBLIC_ROLE`\n     *\n     * Emits a {RoleGranted} event.\n     */\n    function grantRole(uint64 roleId, address account, uint32 executionDelay) external;\n\n    /**\n     * @dev Remove an account from a role, with immediate effect. If the account does not have the role, this call has\n     * no effect.\n     *\n     * Requirements:\n     *\n     * - the caller must be an admin for the role (see {getRoleAdmin})\n     * - revoked role must not be the `PUBLIC_ROLE`\n     *\n     * Emits a {RoleRevoked} event if the account had the role.\n     */\n    function revokeRole(uint64 roleId, address account) external;\n\n    /**\n     * @dev Renounce role permissions for the calling account with immediate effect. If the sender is not in\n     * the role this call has no effect.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * Emits a {RoleRevoked} event if the account had the role.\n     */\n    function renounceRole(uint64 roleId, address callerConfirmation) external;\n\n    /**\n     * @dev Change admin role for a given role.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {RoleAdminChanged} event\n     */\n    function setRoleAdmin(uint64 roleId, uint64 admin) external;\n\n    /**\n     * @dev Change guardian role for a given role.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {RoleGuardianChanged} event\n     */\n    function setRoleGuardian(uint64 roleId, uint64 guardian) external;\n\n    /**\n     * @dev Update the delay for granting a `roleId`.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {RoleGrantDelayChanged} event.\n     */\n    function setGrantDelay(uint64 roleId, uint32 newDelay) external;\n\n    /**\n     * @dev Set the role required to call functions identified by the `selectors` in the `target` contract.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {TargetFunctionRoleUpdated} event per selector.\n     */\n    function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) external;\n\n    /**\n     * @dev Set the delay for changing the configuration of a given target contract.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {TargetAdminDelayUpdated} event.\n     */\n    function setTargetAdminDelay(address target, uint32 newDelay) external;\n\n    /**\n     * @dev Set the closed flag for a contract.\n     *\n     * Closing the manager itself won't disable access to admin methods to avoid locking the contract.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     *\n     * Emits a {TargetClosed} event.\n     */\n    function setTargetClosed(address target, bool closed) external;\n\n    /**\n     * @dev Return the timepoint at which a scheduled operation will be ready for execution. This returns 0 if the\n     * operation is not yet scheduled, has expired, was executed, or was canceled.\n     */\n    function getSchedule(bytes32 id) external view returns (uint48);\n\n    /**\n     * @dev Return the nonce for the latest scheduled operation with a given id. Returns 0 if the operation has never\n     * been scheduled.\n     */\n    function getNonce(bytes32 id) external view returns (uint32);\n\n    /**\n     * @dev Schedule a delayed operation for future execution, and return the operation identifier. It is possible to\n     * choose the timestamp at which the operation becomes executable as long as it satisfies the execution delays\n     * required for the caller. The special value zero will automatically set the earliest possible time.\n     *\n     * Returns the `operationId` that was scheduled. Since this value is a hash of the parameters, it can reoccur when\n     * the same parameters are used; if this is relevant, the returned `nonce` can be used to uniquely identify this\n     * scheduled operation from other occurrences of the same `operationId` in invocations of {execute} and {cancel}.\n     *\n     * Emits a {OperationScheduled} event.\n     *\n     * NOTE: It is not possible to concurrently schedule more than one operation with the same `target` and `data`. If\n     * this is necessary, a random byte can be appended to `data` to act as a salt that will be ignored by the target\n     * contract if it is using standard Solidity ABI encoding.\n     */\n    function schedule(\n        address target,\n        bytes calldata data,\n        uint48 when\n    ) external returns (bytes32 operationId, uint32 nonce);\n\n    /**\n     * @dev Execute a function that is delay restricted, provided it was properly scheduled beforehand, or the\n     * execution delay is 0.\n     *\n     * Returns the nonce that identifies the previously scheduled operation that is executed, or 0 if the\n     * operation wasn't previously scheduled (if the caller doesn't have an execution delay).\n     *\n     * Emits an {OperationExecuted} event only if the call was scheduled and delayed.\n     */\n    function execute(address target, bytes calldata data) external payable returns (uint32);\n\n    /**\n     * @dev Cancel a scheduled (delayed) operation. Returns the nonce that identifies the previously scheduled\n     * operation that is cancelled.\n     *\n     * Requirements:\n     *\n     * - the caller must be the proposer, a guardian of the targeted function, or a global admin\n     *\n     * Emits a {OperationCanceled} event.\n     */\n    function cancel(address caller, address target, bytes calldata data) external returns (uint32);\n\n    /**\n     * @dev Consume a scheduled operation targeting the caller. If such an operation exists, mark it as consumed\n     * (emit an {OperationExecuted} event and clean the state). Otherwise, throw an error.\n     *\n     * This is useful for contract that want to enforce that calls targeting them were scheduled on the manager,\n     * with all the verifications that it implies.\n     *\n     * Emit a {OperationExecuted} event.\n     */\n    function consumeScheduledOp(address caller, bytes calldata data) external;\n\n    /**\n     * @dev Hashing function for delayed operations.\n     */\n    function hashOperation(address caller, address target, bytes calldata data) external view returns (bytes32);\n\n    /**\n     * @dev Changes the authority of a target managed by this manager instance.\n     *\n     * Requirements:\n     *\n     * - the caller must be a global admin\n     */\n    function updateAuthority(address target, address newAuthority) external;\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/access/manager/IAuthority.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAuthority.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Standard interface for permissioning originally defined in Dappsys.\n */\ninterface IAuthority {\n    /**\n     * @dev Returns true if the caller can invoke on a target the function identified by a function selector.\n     */\n    function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed);\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\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":"smart-contracts-public/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\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":"smart-contracts-public/lib/openzeppelin-contracts/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":"smart-contracts-public/lib/openzeppelin-contracts/contracts/utils/Pausable.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 {Context} from \"../utils/Context.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 Pausable is Context {\n    bool private _paused;\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    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\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        _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        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\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 ReentrancyGuard {\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    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\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        // 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        // 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        return _status == ENTERED;\n    }\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"smart-contracts-public/lib/openzeppelin-contracts/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":"smart-contracts-public/src/compliance/IKYCRegistry.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\ninterface IKYCRegistry {\n    function isKYCApproved(address user) external view returns (bool);\n}\n"},{"file_path":"smart-contracts-public/src/deposit/FeeVault.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\nimport {AccessManaged} from \"@openzeppelin/contracts/access/manager/AccessManaged.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title FeeVault\n * @notice Tracks and manages protocol fees for a specific product (Deposits or Redemptions).\n * @dev A dedicated instance is deployed per product. Exactly one contract (the \"recorder\") is\n *      authorized to record fees via {recordFee}. Admins can later claim the accumulated fees.\n */\ncontract FeeVault is AccessManaged, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n\n    // ============ State Variables ============\n\n    /// @notice Total fees accumulated per token\n    mapping(address => uint256) public totalFees;\n\n    /// @notice Total fees claimed per token\n    mapping(address => uint256) public claimedFees;\n\n    /// @notice Address authorized to call {recordFee} for this vault (e.g., DepositProcessor, InstantRedemption, WindowRedemption)\n    address public immutable recorder;\n\n    // ============ Events ============\n\n    event FeeRecorded(address indexed token, uint256 amount);\n    event FeesClaimed(address indexed token, address indexed recipient, uint256 amount);\n\n    // ============ Errors ============\n\n    error OnlyRecorder();\n    error NoFeesToClaim();\n    error InvalidRecipient();\n    error InvalidAddress();\n    error InvalidAmount();\n\n    // ============ Modifiers ============\n\n    modifier onlyRecorder() {\n        if (msg.sender != recorder) revert OnlyRecorder();\n        _;\n    }\n\n    // ============ Constructor ============\n\n    /**\n     * @param _accessManager AccessManager for admin gating of claims\n     * @param _recorder The single contract allowed to record fees\n     */\n    constructor(address _accessManager, address _recorder) AccessManaged(_accessManager) {\n        if (_accessManager == address(0)) revert InvalidAddress();\n        if (_recorder == address(0)) revert InvalidAddress();\n        recorder = _recorder;\n    }\n\n    // ============ External Functions ============\n\n    /**\n     * @notice Record fee collection (only callable by the authorized recorder)\n     * @param token The token fees were collected in\n     * @param amount The amount of fees collected\n     */\n    function recordFee(address token, uint256 amount) external onlyRecorder {\n        if (amount == 0) revert InvalidAmount();\n        totalFees[token] += amount;\n        emit FeeRecorded(token, amount);\n    }\n\n    /**\n     * @notice Claim accumulated fees\n     * @param token The token to claim fees for\n     * @param recipient The address to receive the fees\n     * @return claimable The amount of fees claimed\n     */\n    function claimFees(address token, address recipient)\n        external\n        restricted\n        nonReentrant\n        returns (uint256 claimable)\n    {\n        if (recipient == address(0)) revert InvalidRecipient();\n\n        claimable = totalFees[token] - claimedFees[token];\n        if (claimable == 0) revert NoFeesToClaim();\n\n        claimedFees[token] = totalFees[token];\n\n        IERC20(token).safeTransfer(recipient, claimable);\n\n        emit FeesClaimed(token, recipient, claimable);\n    }\n\n    // ============ View Functions ============\n\n    /**\n     * @notice Get the amount of claimable fees for a token\n     * @param token The token to check\n     * @return The amount of fees that can be claimed\n     */\n    function getClaimableFees(address token) external view returns (uint256) {\n        return totalFees[token] - claimedFees[token];\n    }\n}\n"},{"file_path":"smart-contracts-public/src/pricing/IPriceOracle.sol","source_code":"pragma solidity 0.8.30;\n\n/**\n * @title IPriceOracle\n * @notice Standardized price oracle interface returning WAD‑scaled prices with a status code.\n * @dev Prices MUST be scaled to 1e18 (WAD). Implementations can surface status information such as\n * validity, staleness, capping, or circuit breaker activation.\n */\ninterface IPriceOracle {\n    enum PriceStatus {\n        VALID,\n        CAPPED,\n        INVALID,\n        STALE,\n        VOLATILE,\n        CIRCUIT_BREAKER\n    }\n\n    struct PriceInfo {\n        uint256 price;\n        PriceStatus status;\n    }\n\n    /**\n     * @notice Retrieves the latest price information for the configured token\n     * @return PriceInfo Struct containing the price and its status\n     */\n    function latestPriceInfo() external view returns (PriceInfo memory);\n\n    /**\n     * @notice Retrieves the number of decimals for the token's price feed\n     * @return uint8 Number of decimals\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"smart-contracts-public/src/pricing/IRedemptionReserves.sol","source_code":"pragma solidity 0.8.30;\n\n/**\n * @title IRedemptionReserves\n * @notice Standardized redemption reserves interface returning WAD‑scaled reserves\n */\ninterface IRedemptionReserves {\n    /**\n     * @notice Retrieves the total value of redemption reserves\n     * @param vault Primary storage for redemption reserves\n     * @param custodialWallet Secondary storage (e.g., Fireblocks)\n     * @return uint256 Total value of redemption reserves\n     */\n    function calculateTotalReserveValue(address vault, address custodialWallet) external view returns (uint256);\n   \n}\n"},{"file_path":"smart-contracts-public/src/pricing/PriceRouter.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\nimport \"@openzeppelin/contracts/access/manager/AccessManaged.sol\";\nimport \"../pricing/IPriceOracle.sol\";\n\n/**\n * @title PriceRouter\n * @notice Registry from token → {IPriceOracle}. Used across deposit/redemption/reserve contexts.\n * @dev Returns prices in WAD (1e18). Only VALID or CAPPED statuses are accepted; STALE reverts.\n *\n * **Security**\n * - Oracle assignment is gated by {AccessManaged}. Misconfiguration will cause hard reverts,\n *   which is preferable to using unsafe prices.\n */\ncontract PriceRouter is AccessManaged {\n    // ============ Constants ============\n    // Role identifier for backward compatibility (informational only)\n    bytes32 public constant CONFIG_ROLE = keccak256(\"CONFIG_ROLE\");\n\n    // ============ State ============\n    mapping(address => IPriceOracle) public priceFeeds;\n    string public description;\n\n    // ============ Events ============\n    event PriceFeedSet(address indexed token, address indexed feed);\n    event PriceFeedRemoved(address indexed token);\n\n    // ============ Errors ============\n    error TokenNotConfigured();\n    error InvalidPriceFeed();\n    error StalePrice();\n    error InvalidPrice();\n\n    // ============ Constructor ============\n\n    /**\n     * @notice Initialize the price router\n     * @param _accessManager Address of the AccessManager contract\n     * @param _description Human-readable description of this router instance\n     */\n    constructor(address _accessManager, string memory _description) AccessManaged(_accessManager) {\n        description = _description;\n    }\n\n    // ============ Configuration Functions ============\n\n    /**\n     * @notice Set the price feed for a token\n     * @param token Token address\n     * @param feed Price oracle address\n     */\n    function setPriceFeed(address token, address feed) external restricted {\n        if (feed == address(0)) revert InvalidPriceFeed();\n        priceFeeds[token] = IPriceOracle(feed);\n        emit PriceFeedSet(token, feed);\n    }\n\n    /**\n     * @notice Remove the price feed for a token\n     * @param token Token address\n     */\n    function removePriceFeed(address token) external restricted {\n        delete priceFeeds[token];\n        emit PriceFeedRemoved(token);\n    }\n\n    // ============ View Functions ============\n\n    /**\n     * @notice Get the current price of a token\n     * @param token Token address\n     * @return Price in WAD format (18 decimals)\n     */\n    function getPrice(address token) external view returns (uint256) {\n        IPriceOracle feed = priceFeeds[token];\n        if (address(feed) == address(0)) revert TokenNotConfigured();\n\n        IPriceOracle.PriceInfo memory info = feed.latestPriceInfo();\n\n        // Check for stale price first\n        if (info.status == IPriceOracle.PriceStatus.STALE) {\n            revert StalePrice();\n        }\n\n        // Accept VALID and CAPPED prices\n        if (\n            info.status != IPriceOracle.PriceStatus.VALID\n                && info.status != IPriceOracle.PriceStatus.CAPPED\n        ) {\n            revert InvalidPrice();\n        }\n\n        return info.price;\n    }\n\n    /**\n     * @notice Check if a price feed is configured for a token\n     * @param token Token address\n     * @return True if a price feed is configured\n     */\n    function hasPrice(address token) external view returns (bool) {\n        return address(priceFeeds[token]) != address(0);\n    }\n}\n"},{"file_path":"smart-contracts-public/src/redemption/PayoutTokenRegistry.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\nimport \"@openzeppelin/contracts/access/manager/AccessManaged.sol\";\n\n/**\n * @title PayoutTokenRegistry\n * @notice Tracks the set of tokens that contribute to reserves and manages the active payout token.\n * @dev Pricing is delegated to {PriceRouter}; this contract only records eligibility and schedules switches.\n *\n * - `valueTokens`: tokens whose balances count toward total redemption reserves.\n * - `activePayoutToken`: token actually paid out by redemption modules.\n * - `scheduledPayoutToken`: pending token to become active at next UTC midnight (`switchTime`).\n *\n * **Security considerations**\n * - Only authorized operators (via {AccessManaged}) may configure or switch tokens.\n * - `emergencySwitch` bypasses the schedule and should be protected by a guardian role.\n */\ncontract PayoutTokenRegistry is AccessManaged {\n    // ============ Constants ============\n    // Role identifiers for backward compatibility (informational only)\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN_ROLE\");\n    bytes32 public constant EMERGENCY_ROLE = keccak256(\"EMERGENCY_ROLE\");\n\n    uint256 public constant MAX_VALUE_TOKENS = 20;\n    uint256 private constant SECONDS_PER_DAY = 86400;\n\n    // ============ Types ============\n    struct TokenConfig {\n        bool inValueSet; // Contributes to total value\n        bool payoutEligible; // Can be active payout token\n    }\n\n    // ============ State ============\n    mapping(address => TokenConfig) public tokenConfigs;\n    address[] public valueTokens;\n\n    address public activePayoutToken;\n    address public scheduledPayoutToken;\n    uint256 public switchTime;\n\n    // ============ Events ============\n    event TokenConfigured(address indexed token, bool inValueSet, bool payoutEligible);\n    event TokenRemoved(address indexed token);\n    event PayoutTokenScheduled(address indexed token, uint256 switchTime);\n    event PayoutTokenSwitched(address indexed previousToken, address indexed newToken);\n    event EmergencySwitch(address indexed token);\n\n    // ============ Errors ============\n    error InvalidToken();\n    error TokenNotConfigured();\n    error TokenNotEligible();\n    error TooSoonToSwitch();\n    error NoScheduledSwitch();\n    error AlreadyActive();\n    error TooManyTokens();\n    error CannotRemoveActiveToken();\n    error CannotRemoveScheduledToken();\n\n    // ============ Constructor ============\n\n    /**\n     * @notice Initialize the registry with AccessManager\n     * @param _accessManager Address of the AccessManager contract\n     */\n    constructor(address _accessManager) AccessManaged(_accessManager) {\n        // Role setup is handled in AccessManager\n    }\n\n    // ============ Admin Functions ============\n\n    /**\n     * @notice Configure a token's value set and payout eligibility\n     * @param token Token address\n     * @param inValueSet Whether token contributes to total value\n     * @param payoutEligible Whether token can be active payout token\n     */\n    function setTokenConfig(address token, bool inValueSet, bool payoutEligible)\n        external\n        restricted\n    {\n        if (token == address(0)) revert InvalidToken();\n\n        TokenConfig memory oldConfig = tokenConfigs[token];\n\n        // Handle value set changes\n        if (inValueSet && !oldConfig.inValueSet) {\n            // Adding to value set\n            if (valueTokens.length >= MAX_VALUE_TOKENS) revert TooManyTokens();\n            valueTokens.push(token);\n        } else if (!inValueSet && oldConfig.inValueSet) {\n            // Removing from value set\n            _removeFromValueSet(token);\n        }\n\n        tokenConfigs[token] = TokenConfig(inValueSet, payoutEligible);\n        emit TokenConfigured(token, inValueSet, payoutEligible);\n    }\n\n    /**\n     * @notice Remove a token entirely\n     * @param token Token to remove\n     */\n    function removeToken(address token) external restricted {\n        if (token == activePayoutToken) revert CannotRemoveActiveToken();\n        if (token == scheduledPayoutToken) revert CannotRemoveScheduledToken();\n\n        if (tokenConfigs[token].inValueSet) {\n            _removeFromValueSet(token);\n        }\n\n        delete tokenConfigs[token];\n        emit TokenRemoved(token);\n    }\n\n    /**\n     * @notice Schedule a payout token change for next UTC midnight\n     * @param token Token to become active payout\n     */\n    function schedulePayoutToken(address token) external restricted {\n        TokenConfig memory config = tokenConfigs[token];\n        if (!config.inValueSet && !config.payoutEligible) revert TokenNotConfigured();\n        if (!config.payoutEligible) revert TokenNotEligible();\n        if (token == activePayoutToken) revert AlreadyActive();\n\n        // Schedule for next UTC midnight\n        uint256 currentDay = block.timestamp / SECONDS_PER_DAY;\n        uint256 nextMidnight = (currentDay + 1) * SECONDS_PER_DAY;\n\n        scheduledPayoutToken = token;\n        switchTime = nextMidnight;\n\n        emit PayoutTokenScheduled(token, nextMidnight);\n    }\n\n    /**\n     * @notice Execute scheduled payout token switch\n     * @dev Callable by anyone after switchTime\n     */\n    function executeSwitch() external {\n        if (block.timestamp < switchTime) revert TooSoonToSwitch();\n        if (scheduledPayoutToken == address(0)) revert NoScheduledSwitch();\n\n        // Validate token is STILL eligible\n        TokenConfig memory config = tokenConfigs[scheduledPayoutToken];\n        if (!config.payoutEligible) revert TokenNotEligible();\n\n        address previousToken = activePayoutToken;\n        activePayoutToken = scheduledPayoutToken;\n        scheduledPayoutToken = address(0);\n        switchTime = 0;\n\n        emit PayoutTokenSwitched(previousToken, activePayoutToken);\n    }\n\n    /**\n     * @notice Emergency switch to new payout token\n     * @param token Token to activate immediately\n     */\n    function emergencySwitch(address token) external restricted {\n        TokenConfig memory config = tokenConfigs[token];\n        if (!config.payoutEligible) revert TokenNotEligible();\n\n        address previousToken = activePayoutToken;\n        activePayoutToken = token;\n\n        // Clear any scheduled switch\n        scheduledPayoutToken = address(0);\n        switchTime = 0;\n\n        emit EmergencySwitch(token);\n        emit PayoutTokenSwitched(previousToken, token);\n    }\n\n    // ============ View Functions ============\n\n    /**\n     * @notice Check if token is in value set\n     * @param token Token to check\n     * @return True if token contributes to total value\n     */\n    function isValueToken(address token) external view returns (bool) {\n        return tokenConfigs[token].inValueSet;\n    }\n\n    /**\n     * @notice Check if token can be payout token\n     * @param token Token to check\n     * @return True if eligible for payout\n     */\n    function isPayoutEligible(address token) external view returns (bool) {\n        return tokenConfigs[token].payoutEligible;\n    }\n\n    /**\n     * @notice Get all value tokens\n     * @return Array of tokens in value set\n     */\n    function getValueTokens() external view returns (address[] memory) {\n        return valueTokens;\n    }\n\n    /**\n     * @notice Get value token count\n     * @return Number of tokens in value set\n     */\n    function getValueTokenCount() external view returns (uint256) {\n        return valueTokens.length;\n    }\n\n    // ============ Internal Functions ============\n\n    /**\n     * @notice Remove token from value tokens array\n     * @param token Token to remove\n     */\n    function _removeFromValueSet(address token) private {\n        uint256 length = valueTokens.length;\n        for (uint256 i; i < length; i++) {\n            if (valueTokens[i] == token) {\n                valueTokens[i] = valueTokens[length - 1];\n                valueTokens.pop();\n                return;\n            }\n        }\n    }\n}\n"},{"file_path":"smart-contracts-public/src/redemption/RedemptionVault.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\nimport \"@openzeppelin/contracts/access/manager/AccessManaged.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title RedemptionVault\n * @notice Custodies payout tokens and supports reserved balances for windowed redemptions.\n * @dev The vault keeps lightweight internal accounting (`balances`, `reservedPerAsset`) but always\n * relies on on-chain token balances to avoid token trapping or ledger drift. Only authorized\n * modules can withdraw or reserve.\n *\n * **Security**\n * - Non-reentrant.\n * - `restricted` access via {AccessManaged} for all state-changing operations.\n */\ncontract RedemptionVault is AccessManaged, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    // Custom errors\n\n    error InvalidAsset();\n    error InvalidRecipient();\n    error InvalidAddress();\n    error ZeroAmount();\n    error InsufficientBalance();\n\n    // Functions in this contract are restricted based on AccessManager configuration\n    // Expected roles:\n    // - Admin functions: deposit\n    // - Redeemer functions: withdraw, withdrawReserved, reserveForWindow, releaseFromWindow\n    // - Guardian functions: emergencyWithdraw\n\n    mapping(address => uint256) public balances;\n    mapping(address => uint256) public reservedPerAsset; // Window redemption reservations per asset\n\n    event Deposited(address indexed asset, address indexed from, uint256 amount);\n    event Withdrawn(address indexed asset, address indexed to, uint256 amount);\n    event WindowFundsReserved(address indexed asset, uint256 amount);\n    event WindowFundsReleased(address indexed asset, uint256 amount);\n\n    /// @param accessManager Address of the AccessManager contract\n    constructor(address accessManager) AccessManaged(accessManager) {\n        if (accessManager == address(0)) revert InvalidAddress();\n    }\n\n    /// @notice Deposit assets into the vault\n    /// @dev Restricted to admin role to prevent manipulation of vault balances\n    /// @param asset Address of the asset to deposit\n    /// @param amount Amount to deposit\n    function deposit(address asset, uint256 amount) external restricted {\n        if (asset == address(0)) revert InvalidAsset();\n        if (amount == 0) revert ZeroAmount();\n\n        IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);\n        balances[asset] += amount;\n\n        emit Deposited(asset, msg.sender, amount);\n    }\n\n    /// @notice Withdraw unreserved assets from the vault\n    /// @param asset Address of the asset to withdraw\n    /// @param to Recipient address\n    /// @param amount Amount to withdraw\n    function withdraw(address asset, address to, uint256 amount) external restricted nonReentrant {\n        if (asset == address(0)) revert InvalidAsset();\n        if (to == address(0)) revert InvalidRecipient();\n        if (amount == 0) revert ZeroAmount();\n\n        // Check available balance (on-chain balance minus reservations)\n        uint256 available = _availableBalance(asset);\n        if (available < amount) revert InsufficientBalance();\n\n        // Update ledger if possible (for accounting, but don't let it block withdrawals)\n        if (balances[asset] >= amount) {\n            balances[asset] -= amount;\n        } else {\n            // If ledger is insufficient, set to 0 (tokens came from outside deposit)\n            balances[asset] = 0;\n        }\n\n        IERC20(asset).safeTransfer(to, amount);\n\n        emit Withdrawn(asset, to, amount);\n    }\n\n    /// @notice Withdraw from reserved funds (for window redemption claims)\n    /// @param asset Address of the asset to withdraw\n    /// @param to Recipient address\n    /// @param amount Amount to withdraw from reserved funds\n    function withdrawReserved(address asset, address to, uint256 amount)\n        external\n        restricted\n        nonReentrant\n    {\n        if (asset == address(0)) revert InvalidAsset();\n        if (to == address(0)) revert InvalidRecipient();\n        if (amount == 0) revert ZeroAmount();\n\n        // Check that we have enough reserved funds\n        if (reservedPerAsset[asset] < amount) revert InsufficientBalance();\n\n        // Check we have actual tokens (prevent over-reservation bugs)\n        uint256 onChainBalance = IERC20(asset).balanceOf(address(this));\n        if (onChainBalance < amount) revert InsufficientBalance();\n\n        // Deduct from reserved tracking\n        reservedPerAsset[asset] -= amount;\n\n        // Update ledger if possible (don't let it underflow)\n        if (balances[asset] >= amount) {\n            balances[asset] -= amount;\n        } else {\n            balances[asset] = 0;\n        }\n\n        // Transfer the tokens\n        IERC20(asset).safeTransfer(to, amount);\n\n        emit Withdrawn(asset, to, amount);\n    }\n\n    /// @notice Get available balance of an asset (excluding window reservations)\n    /// @param asset Address of the asset\n    /// @return Available balance not reserved for redemption windows\n    function availableBalance(address asset) external view returns (uint256) {\n        return _availableBalance(asset);\n    }\n\n    /// @dev Internal helper to calculate available balance\n    /// @dev Uses actual on-chain balance to prevent token trapping\n    function _availableBalance(address asset) internal view returns (uint256) {\n        // Use actual on-chain balance minus reservations\n        // This prevents trapped tokens from direct transfers/airdrops\n        uint256 onChainBalance = IERC20(asset).balanceOf(address(this));\n        return\n            onChainBalance > reservedPerAsset[asset] ? onChainBalance - reservedPerAsset[asset] : 0;\n    }\n\n    /// @notice Get total balance held by vault\n    /// @param asset Address of the asset\n    /// @return Total balance held by vault\n    function totalBalance(address asset) external view returns (uint256) {\n        return IERC20(asset).balanceOf(address(this));\n    }\n\n    /// @notice Reserve funds for a redemption window\n    /// @param asset Address of the asset to reserve\n    /// @param amount Amount to reserve for the window\n    function reserveForWindow(address asset, uint256 amount) external restricted {\n        if (asset == address(0)) revert InvalidAsset();\n        // Check we have enough unreserved funds available\n        uint256 available = _availableBalance(asset);\n        if (available < amount) revert InsufficientBalance();\n\n        // Increase the reservation\n        reservedPerAsset[asset] += amount;\n        emit WindowFundsReserved(asset, amount);\n    }\n\n    /// @notice Release window reservation (after claim period expires)\n    /// @param asset Address of the asset to release\n    /// @param amount Amount to release from window reservation\n    function releaseFromWindow(address asset, uint256 amount) external restricted {\n        if (asset == address(0)) revert InvalidAsset();\n        if (reservedPerAsset[asset] < amount) revert InsufficientBalance();\n\n        reservedPerAsset[asset] -= amount;\n        emit WindowFundsReleased(asset, amount);\n    }\n\n    /// @notice Emergency withdrawal by guardian (break-glass)\n    /// @dev Restricted function for emergency use - can withdraw even reserved funds\n    /// @param asset Address of the asset\n    /// @param to Recipient address\n    /// @param amount Amount to withdraw\n    function emergencyWithdraw(address asset, address to, uint256 amount)\n        external\n        restricted\n        nonReentrant\n    {\n        if (asset == address(0)) revert InvalidAsset();\n        if (to == address(0)) revert InvalidRecipient();\n        if (amount == 0) revert ZeroAmount();\n\n        // Use actual on-chain balance and cap the requested withdrawal to what is available\n        uint256 onChainBalance = IERC20(asset).balanceOf(address(this));\n        uint256 withdrawAmount = amount > onChainBalance ? onChainBalance : amount;\n        if (withdrawAmount == 0) revert InsufficientBalance();\n\n        // Update ledger if possible\n        if (balances[asset] >= withdrawAmount) {\n            balances[asset] -= withdrawAmount;\n        } else {\n            balances[asset] = 0;\n        }\n\n        // Adjust window reservations if necessary, ensuring reservations never exceed remaining on-chain balance\n        uint256 remainingBalance = onChainBalance - withdrawAmount;\n        if (reservedPerAsset[asset] > remainingBalance) {\n            reservedPerAsset[asset] = remainingBalance;\n        }\n\n        IERC20(asset).safeTransfer(to, withdrawAmount);\n        emit Withdrawn(asset, to, withdrawAmount);\n    }\n}\n"},{"file_path":"smart-contracts-public/src/token/IShareToken.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.30;\n\n/**\n * @title IShareToken\n * @notice Minimal ERC20-compatible interface expected by the protocol's deposit and redemption flows.\n * @dev Implemented by {ShareToken}. Functions are deliberately narrow to reduce coupling.\n * - All amounts use the token's own decimals.\n * - {mint} and {burn} are typically restricted via AccessManager roles in the implementation.\n */\ninterface IShareToken {\n    function burn(address user, uint256 amount) external;\n    function mint(address to, uint256 amount) external;\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n    function transfer(address to, uint256 amount) external returns (bool);\n    function balanceOf(address account) external view returns (uint256);\n    function decimals() external view returns (uint8);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_accessManager","type":"address"},{"internalType":"address","name":"_shareToken","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_tokenRegistry","type":"address"},{"internalType":"address","name":"_priceRouter","type":"address"},{"internalType":"address","name":"_kyc","type":"address"},{"internalType":"address","name":"_custodialWallet","type":"address"},{"internalType":"address","name":"_redemptionReserves","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"authority","type":"address"}],"name":"AccessManagedInvalidAuthority","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint32","name":"delay","type":"uint32"}],"name":"AccessManagedRequiredDelay","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"AccessManagedUnauthorized","type":"error"},{"inputs":[],"name":"BelowMinimum","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExceedsMaximum","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"GlobalLimitExceeded","type":"error"},{"inputs":[],"name":"InsufficientOutput","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidConfiguration","type":"error"},{"inputs":[],"name":"InvalidDecimals","type":"error"},{"inputs":[],"name":"KYCRequired","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UserLimitExceeded","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newHighWatermark","type":"uint256"}],"name":"DailyReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousToken","type":"address"},{"indexed":true,"internalType":"address","name":"newToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"}],"name":"DailyResetByTokenSwitch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeVault","type":"address"}],"name":"FeeVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"HighWatermarkUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"sharesBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"grossPayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netPayout","type":"uint256"}],"name":"InstantRedemptionProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dailyBps","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"userBps","type":"uint256"}],"name":"LimitsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"min","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"max","type":"uint256"}],"name":"RedemptionRangeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dailyLimit","type":"uint256"}],"name":"RefillNeeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"authority","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"custodialWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dailyGrossSpending","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dailyLimitBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dayPayoutToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeVault","outputs":[{"internalType":"contract FeeVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDailyRedemptions","outputs":[{"internalType":"uint256","name":"day","type":"uint256"},{"internalType":"uint256","name":"spending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRedemptionStatus","outputs":[{"internalType":"bool","name":"kycApproved","type":"bool"},{"internalType":"uint256","name":"remainingDaily","type":"uint256"},{"internalType":"uint256","name":"remainingUser","type":"uint256"},{"internalType":"uint256","name":"minRedemptionAmount","type":"uint256"},{"internalType":"uint256","name":"maxRedemptionAmount","type":"uint256"},{"internalType":"uint256","name":"currentFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRemainingDailyLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRemainingUserLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserDailySpending","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultLowBalanceThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"highWatermark","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isConsumingScheduledOp","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kyc","outputs":[{"internalType":"contract IKYCRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDailyReset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRedemption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRedemption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payoutTokenRegistry","outputs":[{"internalType":"contract PayoutTokenRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedemption","outputs":[{"internalType":"uint256","name":"grossPayout","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"netPayout","type":"uint256"},{"internalType":"bool","name":"available","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"minPayout","type":"uint256"}],"name":"redeemFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionPriceRouter","outputs":[{"internalType":"contract PriceRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionReserves","outputs":[{"internalType":"contract IRedemptionReserves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeVault","type":"address"}],"name":"setFeeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shareToken","outputs":[{"internalType":"contract IShareToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBps","type":"uint16"}],"name":"updateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateHighWatermark","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dailyBps","type":"uint256"},{"internalType":"uint256","name":"_userBps","type":"uint256"}],"name":"updateLimitPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_min","type":"uint256"},{"internalType":"uint256","name":"_max","type":"uint256"}],"name":"updateRedemptionRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userDailyTracking","outputs":[{"internalType":"uint256","name":"lastResetDay","type":"uint256"},{"internalType":"uint256","name":"spending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"userLimitBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract RedemptionVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0000000000000000000000003f0da1c363e34802c6f12f9c27276dc0e6696fd80000000000000000000000005086bf358635b81d8c47c66d1c8b9e567db70c720000000000000000000000005c454f5526e41fbe917b63475cd8ca7e4631b147000000000000000000000000f788624278dc0d5b4e494f834932e6938aa2bdc3000000000000000000000000fe76cf5ed606593fb7764f33627b8d7e0f9fab6600000000000000000000000082f1806aeab5ecb9a485eb041d5ed4940b1239950000000000000000000000009ea38e09f41a9de53972a68268ba0dcc6d2fadf80000000000000000000000007e499842e7634cce793ffd5d44383bb4a2f086e0"}