{"file_path":"nav-oracle-public/contracts/NAVConsumer.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {FunctionsClient} from \"@chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol\";\nimport {FunctionsRequest} from \"@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol\";\nimport {AutomationCompatibleInterface} from \"@chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol\";\nimport {AccessControl} from \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport {INAVConsumer, \n        UnauthorizedNAVUpdateRequest, \n        DeviationCannotBeZero,\n        UpkeepConditionsNotMet,\n        InvalidTargetHour,\n        InvalidTargetMinute,\n        InvalidTimeWindow,\n        InvalidNAVValue,\n        ForceUpdateTooFrequent,\n        InvalidSubscriptionId,\n        InvalidDonId,\n        InvalidSourceCode,\n        InvalidEncryptedSecretsReference,\n        InvalidGasLimit,\n        InvalidReceiverAddress,\n        ZeroAddress,\n        UnexpectedRequestID\n    } from \"./interfaces/INAVConsumer.sol\";\nimport {INAVReceiver} from \"./interfaces/INAVReceiver.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/utils/Pausable.sol\";\n\n/**\n * @title Re Protocol NAV Consumer Contract with Automation\n * @notice This contract receives, stores NAV data and automatically triggers daily updates\n * @dev Implements both Chainlink Functions consumer and Chainlink Automation for scheduled updates\n * \n * Contract Security:\n * - Uses AccessControl for role-based permissions:\n *   - ADMIN_ROLE: Can configure all parameters and settings\n *   - UPDATER_ROLE: Can trigger NAV updates\n *   - EMERGENCY_UPDATER_ROLE: Can force update NAV values directly\n *   - KEEPER_ROLE: Can perform upkeep\n * - Uses ReentrancyGuard to prevent reentrancy attacks during NAV updates and external calls\n * - Includes deviation checks to prevent erroneous NAV updates\n * - Handles failure gracefully when updating NAV receivers\n * \n * Automation Flow:\n * 1. checkUpkeep validates if an update should run based on time window and elapsed time\n * 2. performUpkeep makes the actual Chainlink Functions request when conditions are met\n * 3. fulfillRequest processes the response and updates NAV values\n * \n * Security Considerations:\n * - NAV receiver could be malicious (try/catch pattern is used)\n * - Oracle responses are validated for format and reasonableness\n * - Force updates have time limitations and require special role\n * - All parameters have validation and sanitization\n * - Zero addresses are explicitly prevented\n */\ncontract NAVConsumer is INAVConsumer, FunctionsClient, AutomationCompatibleInterface, AccessControl, ReentrancyGuard, Pausable {\n    /// @notice Role that can configure all parameters and settings\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN_ROLE\");\n    \n    /// @notice Role that can trigger NAV updates\n    bytes32 public constant UPDATER_ROLE = keccak256(\"UPDATER_ROLE\");\n    \n    /// @notice Role that can force update NAV values directly\n    bytes32 public constant EMERGENCY_UPDATER_ROLE = keccak256(\"EMERGENCY_UPDATER_ROLE\");\n    \n    /// @notice Role that can perform upkeep\n    bytes32 public constant KEEPER_ROLE = keccak256(\"KEEPER_ROLE\");\n    \n    /// @notice Minimum time required between force updates (4 hours)\n    /// @dev Prevents abuse of force update mechanism and ensures time for proper review between emergency updates\n    uint256 public constant MIN_FORCE_UPDATE_INTERVAL = 4 hours;\n\n    \n    using FunctionsRequest for FunctionsRequest.Request;\n\n    /// @notice State variables for NAV data\n    /// @dev Stores the latest Chainlink Functions request ID\n    bytes32 public latestRequestId;\n    /// @dev Current NAV value with 18 decimal places\n    uint256 internal latestNAV;\n    /// @dev Timestamp when the current NAV was updated\n    uint256 public latestTimestamp;\n    /// @dev Previous NAV value before the current update\n    uint256 internal previousNAV;\n    /// @dev Timestamp when the previous NAV was updated\n    uint256 public previousTimestamp;\n    \n    /// @notice Chainlink Functions configuration\n    /// @dev DON ID for the Chainlink Functions network\n    bytes32 public donId;\n    /// @dev Subscription ID for billing Chainlink Functions requests\n    uint64 public subscriptionId;\n    /// @dev Gas limit for the fulfillRequest callback function\n    uint32 internal callbackGasLimit;\n    /// @dev JavaScript source code executed by Chainlink Functions\n    string internal source;\n    /// @dev Reference to encrypted secrets used by the source code\n    bytes internal encryptedSecretsReference;\n\n    /// @notice Chainlink Automation configuration\n    /// @dev Target hour (0-23) in UTC for daily updates - default 23:00\n    uint256 public targetHour = 23;\n    /// @dev Target minute (0-59) in UTC for daily updates - default 45 minutes\n    uint256 public targetMinute = 45;\n    \n    /// @dev Time window in seconds during which updates are allowed - default 15 minutes (900 seconds)\n    /// @notice This defines how long after the target time an update can be performed\n    uint256 public timeWindow = 900;\n    \n    /// @dev Timestamp of the last successful automated update via Chainlink Automation\n    /// @notice Used to enforce minimum time between automated updates (20 hours)\n    uint256 public lastAutomatedUpdateTimestamp;\n    \n    /// @dev Timestamp of the last forced update via emergency mechanism\n    /// @notice Used to enforce minimum time between force updates (4 hours)\n    uint256 public lastForceUpdateTimestamp;\n\n    /// @dev Flag to enable or disable the automation feature\n    /// @notice When disabled, checkUpkeep will always return false\n    bool public automationEnabled = true;\n    \n    /// @notice NAV deviation check configuration\n    /// @dev Maximum allowed deviation in basis points - default 10% (1000 basis points)\n    /// @notice Used to reject NAV updates with suspiciously large changes\n    uint256 public maxDeviationBps = 1000;\n    /// @dev Flag to enable or disable the deviation check feature\n    /// @notice When disabled, any NAV value will be accepted regardless of deviation\n    bool public deviationCheckEnabled = true;\n    \n    /// @notice The contract that receives NAV updates\n    /// @dev Must implement INAVReceiver interface, can be set to zero address if not needed\n    INAVReceiver public navReceiver;\n    \n    /**\n     * @notice Constructor initializes the contract with the Chainlink Functions router address and role assignments\n     * @param router The address of the Chainlink Functions router\n     * @param admin The address to assign as admin\n     * @param updater The address to assign as updater\n     * @param emergencyUpdater The address to assign as emergency updater\n     */\n    constructor(\n        address router,\n        address admin,\n        address updater,\n        address emergencyUpdater\n    ) FunctionsClient(router) {\n        if (router == address(0)) revert ZeroAddress(\"router\");\n        if (admin == address(0)) revert ZeroAddress(\"admin\");\n        if (updater == address(0)) revert ZeroAddress(\"updater\");\n        if (emergencyUpdater == address(0)) revert ZeroAddress(\"emergencyUpdater\");\n        \n        callbackGasLimit = 300000; // Initial value well above minimum\n        \n        _grantRole(DEFAULT_ADMIN_ROLE, admin);\n        _grantRole(ADMIN_ROLE, admin);\n        _grantRole(UPDATER_ROLE, updater);\n        _grantRole(EMERGENCY_UPDATER_ROLE, emergencyUpdater);\n        _grantRole(KEEPER_ROLE, admin); // Grant KEEPER_ROLE to admin initially\n    }\n\n    /**\n     * @notice Enable or disable the automation feature\n     * @param enabled True to enable, false to disable\n     * @dev Only callable by admin role\n     */\n    function setAutomationEnabled(bool enabled) external virtual override onlyRole(ADMIN_ROLE) {\n        automationEnabled = enabled;\n        emit AutomationEnabledChanged(enabled, msg.sender);\n    }\n\n    /**\n     * @notice Configure the Chainlink Functions parameters\n     * @param _subscriptionId The Chainlink Functions subscription ID for billing\n     * @param _donId The Decentralized Oracle Network ID\n     * @param _source The JavaScript source code to be executed by Chainlink Functions\n     * @param _encryptedSecretsReference Reference to encrypted secrets for the source code\n     * @dev Only callable by admin role\n     */\n    function configure(\n        uint64 _subscriptionId,\n        bytes32 _donId,\n        string calldata _source,\n        bytes calldata _encryptedSecretsReference\n    ) external override onlyRole(ADMIN_ROLE) {\n        if (_subscriptionId == 0) revert InvalidSubscriptionId();\n        if (_donId == bytes32(0)) revert InvalidDonId();\n        if (bytes(_source).length == 0) revert InvalidSourceCode();\n        if (_encryptedSecretsReference.length == 0) revert InvalidEncryptedSecretsReference();\n        \n        subscriptionId = _subscriptionId;\n        donId = _donId;\n        source = _source;\n        encryptedSecretsReference = _encryptedSecretsReference;\n        \n        // Calculate hashes of source and secrets reference\n        bytes32 sourceCodeHash = keccak256(bytes(_source));\n        bytes32 secretsReferenceHash = keccak256(_encryptedSecretsReference);\n        \n        emit ConfigurationUpdated(_subscriptionId, _donId, sourceCodeHash, secretsReferenceHash, msg.sender);\n    }\n\n    /// @notice Minimum gas needed for fulfillRequest based on testing\n    uint32 public constant MIN_CALLBACK_GAS_LIMIT = 100000;\n    \n    /**\n     * @notice Set the gas limit for the Chainlink Functions callback\n     * @param _callbackGasLimit Gas limit for the fulfillRequest callback function\n     * @dev Only callable by admin role\n     */\n    function setCallbackGasLimit(uint32 _callbackGasLimit) external override onlyRole(ADMIN_ROLE) {\n        if (_callbackGasLimit < MIN_CALLBACK_GAS_LIMIT) revert InvalidGasLimit(MIN_CALLBACK_GAS_LIMIT);\n        \n        uint32 oldLimit = callbackGasLimit;\n        callbackGasLimit = _callbackGasLimit;\n        emit CallbackGasLimitUpdated(oldLimit, _callbackGasLimit, msg.sender);\n    }\n\n    /**\n     * @notice Request a NAV update from Chainlink Functions\n     * @return requestId The unique ID for this request\n     * @dev Only callable by admin or updater roles\n     */\n    function requestNAV() public virtual override whenNotPaused returns (bytes32 requestId) {\n        // Ensure only authorized callers can trigger NAV updates\n        if (!(hasRole(ADMIN_ROLE, msg.sender) || hasRole(UPDATER_ROLE, msg.sender))) {\n            revert UnauthorizedNAVUpdateRequest();\n        }\n        \n        // Call the internal implementation that contains the actual request logic\n        return _performRequestNAV();\n    }\n    \n    /**\n     * @notice Internal implementation of the NAV request logic\n     * @dev Separated to allow performUpkeep to bypass the authorization check\n     * @dev Validates all configuration parameters before making the request\n     * @dev Emits NAVRequestSent event with request ID\n     * @return requestId The ID of the Chainlink Functions request\n     */\n    function _performRequestNAV() internal virtual returns (bytes32 requestId) {\n        // Validate configuration components individually for detailed errors\n        if (bytes(source).length == 0) revert InvalidSourceCode();\n        if (subscriptionId == 0) revert InvalidSubscriptionId();\n        if (donId == bytes32(0)) revert InvalidDonId();\n        if (callbackGasLimit < MIN_CALLBACK_GAS_LIMIT) revert InvalidGasLimit(MIN_CALLBACK_GAS_LIMIT);\n        \n        // Create and initialize the Chainlink Functions request\n        FunctionsRequest.Request memory req;\n        req.initializeRequestForInlineJavaScript(source);\n\n        // Add encrypted secrets reference if provided\n        if (encryptedSecretsReference.length > 0) {\n            req.addSecretsReference(encryptedSecretsReference);\n        }\n\n        // Send the request to Chainlink Functions\n        requestId = _sendRequest(\n            req.encodeCBOR(),\n            subscriptionId,\n            callbackGasLimit,\n            donId\n        );\n\n        // Store the request ID and emit event\n        latestRequestId = requestId;\n        emit NAVRequestSent(requestId);\n        return requestId;\n    }\n\n    /**\n     * @notice Set the address of the NAV receiver contract\n     * @param _navReceiver The address of the contract implementing INAVReceiver\n     * @dev Only callable by admin role, cannot be zero address\n     */\n    function setNAVReceiver(address _navReceiver) external onlyRole(ADMIN_ROLE) {\n        if (_navReceiver == address(0)) revert InvalidReceiverAddress();\n        navReceiver = INAVReceiver(_navReceiver);\n        emit NAVReceiverUpdated(_navReceiver);\n    }\n\n    /**\n     * @notice Internal function to update NAV receiver with latest NAV value\n     * @param navValue The NAV value to set in the receiver contract\n     * @dev Uses try/catch pattern to handle potential failures in the receiver contract\n     * @dev Will not revert if the receiver fails - NAV updates succeed regardless of receiver state\n     * @dev Emits NAVReceiverUpdateFailed event if the receiver call fails\n     * @dev Does nothing if navReceiver is not set (zero address)\n     */\n    function _updateNAVReceiver(uint256 navValue) internal {\n        // Call the NAV receiver to update the share price if it's set\n        if (address(navReceiver) != address(0)) {\n            try navReceiver.setSharePrice(navValue) {\n                // Successfully updated the share price - nothing more to do\n            } catch (bytes memory /* reason */) {\n                // Receiver call failed, but we don't want to revert the entire NAV update\n                emit NAVReceiverUpdateFailed(navValue, address(navReceiver));\n            }\n        }\n    }\n\n    /**\n     * @notice Callback function for Chainlink Functions to deliver the response\n     * @param requestId The ID of the request being fulfilled\n     * @param response The response data from Chainlink Functions (NAV value)\n     * @param err Error message if the request failed\n     * @dev Contains extensive validation of response format and data\n     * @dev Protected against reentrancy with ReentrancyGuard\n     * @dev Performs deviation check to prevent erroneous NAV updates\n     * @dev Updates NAV data storage and propagates to NAV receiver if successful\n     * @dev Emits appropriate events based on result (success, failure, deviation)\n     */\n    function fulfillRequest(\n        bytes32 requestId,\n        bytes memory response,\n        bytes memory err\n    ) internal override nonReentrant {\n        // Verify that the response is for the expected request\n        if (latestRequestId != requestId) {\n            revert UnexpectedRequestID(requestId);\n        }\n        \n        // First, check for errors from the Chainlink Functions service\n        if (err.length > 0) {\n            emit NAVRequestFailed(requestId, string(err));\n            return;\n        }\n        \n        // Check if response data exists\n        if (response.length == 0) {\n            emit NAVRequestFailed(requestId, \"Empty response data\");\n            return;\n        }\n        \n        // Check if response has minimum length for a uint256\n        if (response.length < 32) {\n            emit NAVRequestFailed(requestId, \"Malformed response data - insufficient length\");\n            return;\n        }\n        \n        // Validate response format for a uint256\n        if (response.length != 32 && response.length != 64) {\n            emit NAVRequestFailed(requestId, \"Invalid response length for uint256\");\n            return;\n        }\n        \n        // Decode the response - we've already validated format above\n        uint256 navValue = abi.decode(response, (uint256));\n        \n        // Reject zero NAV values\n        if (navValue == 0) {\n            emit NAVRequestFailed(requestId, \"Cannot update with zero NAV value\");\n            return;\n        }\n        \n        // Check for excessive deviation if enabled and we have an initial value\n        if (deviationCheckEnabled && latestNAV > 0) {\n            // Calculate absolute difference safely\n            uint256 changeAbs;\n            if (navValue > latestNAV) {\n                changeAbs = navValue - latestNAV;\n            } else {\n                changeAbs = latestNAV - navValue;\n            }\n            \n            // Calculate deviation in basis points\n            uint256 deviationBps = (changeAbs * 10000) / latestNAV;\n            \n            // If deviation exceeds limit, reject the update and emit event with detailed error\n            if (deviationBps > maxDeviationBps) {\n                emit ExcessiveNAVDeviation(requestId, navValue, latestNAV, deviationBps);\n                emit PausedDueToDeviation(requestId, navValue, latestNAV, deviationBps);\n                _pause();\n                return; // Reject update but don't revert\n            }\n        }\n        \n        // Update the NAV data\n        previousNAV = latestNAV;\n        previousTimestamp = latestTimestamp;\n        latestNAV = navValue;\n        latestTimestamp = block.timestamp;\n        \n        // Update the NAV receiver\n        _updateNAVReceiver(navValue);\n        \n        emit NAVFulfilled(requestId, navValue);\n        emit NAVUpdated(block.timestamp, navValue);\n    }\n    \n\n    /**\n     * @notice Determine if upkeep is needed based on time (for Chainlink Automation)\n     * @return upkeepNeeded Boolean indicating if upkeep is needed\n     * @return performData The data to be used in performUpkeep (empty in this case)\n     * @dev Checks if automation is enabled\n     * @dev Calculates current UTC time components (hour, minute, seconds)\n     * @dev Determines if current time is within the configured target window\n     * @dev Checks if enough time has passed since last update (20+ hours)\n     * @dev Returns true only when all conditions are met\n     */\n    function checkUpkeep(bytes calldata /* checkData */) \n        external \n        view \n        override \n        returns (bool upkeepNeeded, bytes memory performData) \n    {\n        // Skip check if automation is disabled\n        if (!automationEnabled || paused()) {\n            return (false, \"\");\n        }\n        \n        // Get current UTC time components\n        uint256 timestamp = block.timestamp;\n        uint256 secondsInDay = timestamp % 86400; // Seconds since midnight UTC\n        uint256 currentHour = secondsInDay / 3600;\n        uint256 currentMinute = (secondsInDay % 3600) / 60;\n        \n        // Calculate target time in seconds since midnight UTC\n        uint256 targetTimeSeconds = (targetHour * 3600) + (targetMinute * 60);\n        \n        // Calculate current time in seconds since midnight UTC\n        uint256 currentTimeSeconds = (currentHour * 3600) + (currentMinute * 60) + (secondsInDay % 60);\n        \n        // Check if we're in the target time window (23:45-23:50 UTC)\n        bool inTimeWindow = currentTimeSeconds >= targetTimeSeconds && \n                           currentTimeSeconds < (targetTimeSeconds + timeWindow);\n        \n        // Check if it's been more than 20 hours since the last update\n        bool enoughTimePassed = (timestamp - lastAutomatedUpdateTimestamp) > 20 hours;\n        \n        // Upkeep is needed if we're in the target time window AND it's been enough time since the last update\n        upkeepNeeded = inTimeWindow && enoughTimePassed;\n        \n        // We don't need to pass any data to performUpkeep\n        performData = \"\";\n        \n        return (upkeepNeeded, performData);\n    }\n    \n    /**\n     * @notice Perform the upkeep by requesting a NAV update\n     * @dev Verifies upkeep conditions via checkUpkeep before proceeding\n     * @dev Reverts with UpkeepConditionsNotMet if conditions aren't satisfied\n     * @dev Calls _performRequestNAV to initiate Chainlink Functions request\n     * @dev Updates lastAutomatedUpdateTimestamp and emits AutomatedUpdateTriggered event\n     */\n    function performUpkeep(bytes calldata /* performData */) external override(INAVConsumer, AutomationCompatibleInterface) whenNotPaused onlyRole(KEEPER_ROLE) {\n        // Check if upkeep conditions are satisfied\n        (bool upkeepNeeded, ) = this.checkUpkeep(\"\");\n        if (!upkeepNeeded) {\n            revert UpkeepConditionsNotMet();\n        }\n\n        // Update the last automated update timestamp BEFORE external interactions\n        lastAutomatedUpdateTimestamp = block.timestamp;\n        \n        // Emit event\n        emit AutomatedUpdateTriggered(block.timestamp);\n\n        // Perform NAV update (external interaction)\n        _performRequestNAV();\n    }\n\n    \n    /**\n     * @notice Set the maximum allowed deviation for NAV updates in basis points\n     * @param _maxDeviationBps The maximum allowed deviation (e.g., 1000 = 10%)\n     * @dev Only callable by admin role, cannot be set to zero\n     */\n    function setMaxDeviation(uint256 _maxDeviationBps) external override onlyRole(ADMIN_ROLE) {\n        if (_maxDeviationBps == 0) {\n            revert DeviationCannotBeZero();\n        }\n        maxDeviationBps = _maxDeviationBps;\n        emit MaxDeviationUpdated(_maxDeviationBps);\n    }\n    \n    /**\n     * @notice Enable or disable the deviation check feature\n     * @param _enabled True to enable, false to disable deviation checks\n     * @dev Only callable by admin role\n     */\n    function setDeviationCheckEnabled(bool _enabled) external override onlyRole(ADMIN_ROLE) {\n        deviationCheckEnabled = _enabled;\n        emit DeviationCheckToggled(_enabled);\n    }\n    \n    /**\n     * @notice Force update the NAV value, bypassing the Chainlink Functions request\n     * @param _navValue The NAV value to set\n     * @param _reason Description explaining why this force update is necessary\n     * @dev Only callable by emergency updater role, subject to time restrictions\n     */\n    function forceNAVUpdate(\n        uint256 _navValue, \n        string calldata _reason\n    ) external override whenNotPaused onlyRole(EMERGENCY_UPDATER_ROLE) nonReentrant {\n        // Basic validation to prevent clearly erroneous values\n        if (_navValue == 0) revert InvalidNAVValue(0);\n        \n        // Enforce minimum time between forced updates\n        uint256 timeSinceLastForceUpdate = block.timestamp - lastForceUpdateTimestamp;\n        if (lastForceUpdateTimestamp > 0 && timeSinceLastForceUpdate < MIN_FORCE_UPDATE_INTERVAL) {\n            revert ForceUpdateTooFrequent(timeSinceLastForceUpdate, MIN_FORCE_UPDATE_INTERVAL);\n        }\n        \n        // Calculate deviation for transparency, even though we're bypassing checks\n        uint256 deviationBps = 0;\n        if (latestNAV > 0) {\n            uint256 changeAbs = _navValue > latestNAV \n                ? _navValue - latestNAV \n                : latestNAV - _navValue;\n            deviationBps = (changeAbs * 10000) / latestNAV;\n        }\n        \n        // Update the NAV data\n        previousNAV = latestNAV;\n        previousTimestamp = latestTimestamp;\n        latestNAV = _navValue;\n        latestTimestamp = block.timestamp;\n        lastForceUpdateTimestamp = block.timestamp;\n        \n        // Update the NAV receiver\n        _updateNAVReceiver(_navValue);\n        \n        // Emit events with enhanced information\n        emit NAVForceUpdated(block.timestamp, _navValue, deviationBps, _reason, msg.sender);\n        emit NAVUpdated(block.timestamp, _navValue);\n    }\n\n    /**\n     * @notice Get the current NAV value and its timestamp\n     * @return nav The latest NAV value with 18 decimal places\n     * @return timestamp The timestamp when this NAV value was last updated\n     */\n    function getCurrentNAV() external view override whenNotPaused returns (uint256 nav, uint256 timestamp) {\n        return (latestNAV, latestTimestamp);\n    }\n\n    /**\n     * @notice Get the previous NAV value and its timestamp\n     * @return nav The previous NAV value with 18 decimal places\n     * @return timestamp The timestamp when the previous NAV value was updated\n     */\n    function getPreviousNAV() external view override whenNotPaused returns (uint256 nav, uint256 timestamp) {\n        return (previousNAV, previousTimestamp);\n    }\n\n    /**\n     * @notice Calculate the percentage change between latest and previous NAV\n     * @return percentageChange The percentage change with 8 decimal places (e.g., 100000000 = 1%)\n     * @dev Returns 0 if there is no previous NAV\n     */\n    function getPercentageChange() external view override whenNotPaused returns (int256 percentageChange) {\n        if (previousNAV == 0) return 0;\n        \n        // Calculate absolute difference\n        uint256 changeAbs = latestNAV >= previousNAV \n            ? latestNAV - previousNAV \n            : previousNAV - latestNAV;\n        \n        // Calculate percentage change using uint256 math\n        uint256 percentageChangeAbs = (changeAbs * 100000000) / previousNAV;\n        \n        // Apply sign to result (safe cast since percentage value is much smaller)\n        percentageChange = latestNAV >= previousNAV \n            ? int256(percentageChangeAbs) \n            : -int256(percentageChangeAbs);\n        \n        return percentageChange;\n    }\n    \n    /**\n     * @notice Get the number of decimal places used in NAV values\n     * @return The number of decimal places (18)\n     * @dev NAV values are fixed-point numbers with 18 decimal places\n     * @dev Follows ERC20 convention for better integration with other protocols\n     */\n    function decimals() external pure override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @notice Update automation scheduling parameters\n     * @param _targetHour New target hour (0-23) for the daily update\n     * @param _targetMinute New target minute (0-59) for the daily update\n     * @param _timeWindow New time window in seconds\n     * @dev Only callable by admin role, includes validation of parameters\n     */\n    function setAutomationTimeParameters(uint256 _targetHour, uint256 _targetMinute, uint256 _timeWindow) external onlyRole(ADMIN_ROLE) {\n        if (_targetHour >= 24) revert InvalidTargetHour();\n        if (_targetMinute >= 60) revert InvalidTargetMinute();\n        // Time window must be between 5 minutes and 4 hours\n        if (_timeWindow < 300 || _timeWindow >= 14400) revert InvalidTimeWindow();\n        targetHour = _targetHour;\n        targetMinute = _targetMinute;\n        timeWindow = _timeWindow;\n        emit AutomationParametersUpdated(_targetHour, _targetMinute, _timeWindow);\n    }\n\n    /**\n     * @notice Pause the contract\n     * @dev Only callable by admin role\n     */\n    function pause() external onlyRole(ADMIN_ROLE) {\n        _pause();\n    }\n    \n    /**\n     * @notice Unpause the contract\n     * @dev Only callable by admin role\n     */\n    function unpause() external onlyRole(ADMIN_ROLE) {\n        _unpause();\n    }\n}","deployed_bytecode":"0x608060405234801561001057600080fd5b506004361061030a5760003560e01c806375b238fc1161019c578063b3d03582116100ee578063dd3a9a1011610097578063f063aa3311610071578063f063aa3314610690578063f475877514610699578063f7ced0e7146106a257600080fd5b8063dd3a9a1014610668578063dddbc04914610670578063eb5f23a61461068357600080fd5b8063d547741f116100c8578063d547741f14610640578063d966a59414610653578063daf6bce41461066057600080fd5b8063b3d035821461060f578063cc6dfe791461062e578063d2f343c71461063757600080fd5b806391d1485411610150578063a217fddf1161012a578063a217fddf146105eb578063a4eb718c146105f3578063a66143821461060657600080fd5b806391d148541461058e5780639bdcaf59146105c55780639c66e162146105d857600080fd5b80638205bf6a116101815780638205bf6a146105745780638456cb591461057d5780638dbe7b9d1461058557600080fd5b806375b238fc1461053a57806379e666221461056157600080fd5b806336568abe1161026057806354e4d19a11610209578063693de592116101e3578063693de592146104ea5780636e04ff0d146104f2578063721be4221461051357600080fd5b806354e4d19a146104b95780635953de96146104c25780635c975abb146104df57600080fd5b8063424562131161023a578063424562131461046c5780634585e33b1461047f57806347e633801461049257600080fd5b806336568abe146104485780633ee7a7011461045b5780633f4ba83a1461046457600080fd5b80631d9ff6e4116102c25780632f2ff15d1161029c5780632f2ff15d146103ff578063313ce56714610412578063364bc15a1461042157600080fd5b80631d9ff6e4146103a3578063248a9ca3146103ac5780632c2f03e0146103cf57600080fd5b80630ca76175116102f35780630ca761751461036457806314f69ebe146103795780631aa46f591461038c57600080fd5b806301ffc9a71461030f57806309c1ba2e14610337575b600080fd5b61032261031d3660046129d4565b6106b5565b60405190151581526020015b60405180910390f35b60095461034b9067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032e565b610377610372366004612adb565b61074e565b005b610377610387366004612b8f565b6107eb565b61039560035481565b60405190815260200161032e565b61039560075481565b6103956103ba366004612c2d565b60009081526020819052604090206001015490565b6013546103e79061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161032e565b61037761040d366004612c62565b61098e565b6040516012815260200161032e565b6103957ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab81565b610377610456366004612c62565b6109b9565b61039560125481565b610377610a0a565b61037761047a366004612c8e565b610a3f565b61037761048d366004612cda565b610c20565b6103957f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab81565b61039561384081565b6104ca610d5b565b6040805192835260208301919091520161032e565b60025460ff16610322565b6104ca610d72565b610505610500366004612cda565b610d89565b60405161032e929190612d6c565b6103957f9d1945eeb09f3a9323e5f22a567caed248092672554a0b04901240709fb1347681565b6103957fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b61037761056f366004612d9d565b610ec8565b61039560055481565b610377610f3c565b61039560085481565b61032261059c366004612c62565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6103776105d3366004612dba565b610f6e565b6103776105e6366004612de6565b6110ab565b610395600081565b610377610601366004612e01565b61117f565b610395600c5481565b610619620186a081565b60405163ffffffff909116815260200161032e565b610395600f5481565b610395600e5481565b61037761064e366004612c62565b61124e565b6011546103229060ff1681565b610395611273565b61039561132b565b61037761067e366004612c2d565b6113be565b6013546103229060ff1681565b61039560105481565b610395600d5481565b6103776106b0366004612d9d565b61145f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061074857507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b336001600160a01b037f00000000000000000000000065dcc24f8ff9e51f10dcc7ed1e4e2a61e6e14bd616146107b0576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107bb8383836114ca565b60405183907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756108158161194e565b8667ffffffffffffffff1660000361084057604051630ebd8d1960e11b815260040160405180910390fd5b8561085e576040516391f7443960e01b815260040160405180910390fd5b600084900361088057604051631161b0b360e01b815260040160405180910390fd5b60008290036108bb576040517f08974bc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff191667ffffffffffffffff89161790556008869055600a6108ea858783612ea8565b50600b6108f8838583612ea8565b506000858560405161090b929190612f68565b6040518091039020905060008484604051610927929190612f68565b6040805191829003822067ffffffffffffffff8c168352602083018b905290820184905260608201819052915033907fd0460bc9a3d662ffa248c53ead902bfc09de1660e8bf7e202467ba7d9c525b849060800160405180910390a2505050505050505050565b6000828152602081905260409020600101546109a98161194e565b6109b38383611958565b50505050565b6001600160a01b03811633146109fb576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a058282611a02565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610a348161194e565b610a3c611a85565b50565b610a47611ad7565b7f9d1945eeb09f3a9323e5f22a567caed248092672554a0b04901240709fb13476610a718161194e565b610a79611b16565b83600003610abb576040517fc0c148d4000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b600060105442610acb9190612f8e565b90506000601054118015610ae0575061384081105b15610b22576040517f29108fcd000000000000000000000000000000000000000000000000000000008152600481018290526138406024820152604401610ab2565b60045460009015610b785760006004548711610b4b5786600454610b469190612f8e565b610b58565b600454610b589088612f8e565b600454909150610b6a82612710612fa1565b610b749190612fce565b9150505b6004805460065560058054600755908790554290819055601055610b9b86611b59565b427f2d7f7ae13710a5fc7ea85533ac930ce3bb3317b7282af073f3645dd3e6a412f48783888833604051610bd3959493929190612fe2565b60405180910390a2427f224bbf4ba043354bee6487d05aa90892db4426afe8e3aa79007d0eae1b985ebc87604051610c0d91815260200190565b60405180910390a250506109b360018055565b610c28611ad7565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab610c528161194e565b6040517f6e04ff0d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201819052903090636e04ff0d90604401600060405180830381865afa158015610cb1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cd99190810190613032565b50905080610d13576040517fa37ddd2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42600f8190556040519081527f883e407cc0ae0d12f7a01c2fdc3bd21afa3181401fc985b413f52316341eabe89060200160405180910390a1610d54611c5d565b5050505050565b600080610d66611ad7565b50506006546007549091565b600080610d7d611ad7565b50506004546005549091565b60115460009060609060ff161580610da3575060025460ff165b15610dc05750506040805160208101909152600080825290610ec1565b426000610dd062015180836130bf565b90506000610de0610e1083612fce565b90506000603c610df2610e10856130bf565b610dfc9190612fce565b90506000600d54603c610e0f9190612fa1565b600c54610e1e90610e10612fa1565b610e2891906130d3565b90506000610e37603c866130bf565b610e4284603c612fa1565b610e4e86610e10612fa1565b610e5891906130d3565b610e6291906130d3565b90506000828210158015610e815750600e54610e7e90846130d3565b82105b9050600062011940600f5489610e979190612f8e565b119050818015610ea45750805b995060405180602001604052806000815250985050505050505050505b9250929050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610ef28161194e565b6011805460ff191683151590811790915560405190815233907f84ea38e2d33114764b52620adfd1efa8dbc74614c1e2cdb6b16c16ffb798a2c59060200160405180910390a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f668161194e565b610a3c611f18565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f988161194e565b60188410610fd2576040517f6bae8b6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c831061100c576040517f053c1f4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012c82108061101e57506138408210155b15611055576040517fb11cd48100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c849055600d839055600e82905560408051858152602081018590529081018390527f7ba3a5f107a3591b604d817104b45edf844cd83ed1b93401dc66c4ac37a5bad09060600160405180910390a150505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756110d58161194e565b6001600160a01b038216611115576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601380547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101006001600160a01b038516908102919091179091556040517fee26f3ffb0fd9f2274be5e2c82a9e710e999b2da7d338b2d662d2540b14cf1bb90600090a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756111a98161194e565b620186a063ffffffff831610156111d857604051630298914960e41b8152620186a06004820152602401610ab2565b6009805463ffffffff848116680100000000000000008181026bffffffff000000000000000019851617909455604080519490930490911680845260208401919091529133917fa33fca53ddda42966636288d60b6f6c9167d025c6e8e960f01cdd4a036932a76910160405180910390a2505050565b6000828152602081905260409020600101546112698161194e565b6109b38383611a02565b600061127d611ad7565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16806112e857503360009081527f738678fe42df6a4211eb7628ac9b056229141839eb4f4ef4cc249f1d36e8c921602052604090205460ff165b61131e576040517f9cf11bdb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611326611c5d565b905090565b6000611335611ad7565b6006546000036113455750600090565b60006006546004541015611368576004546006546113639190612f8e565b611378565b6006546004546113789190612f8e565b90506000600654826305f5e10061138f9190612fa1565b6113999190612fce565b905060065460045410156113b5576113b0816130e6565b6113b7565b805b9250505090565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756113e88161194e565b81600003611422576040517f5880a9f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60128290556040518281527f3f9ef5ed5d378ef819698e4b3c710d362f981f90087b428b7a1ee1e716d689d5906020015b60405180910390a15050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756114898161194e565b6013805460ff19168315159081179091556040519081527f4b3846e59e75439d5fd0202dae15523da9daacc4b91b1e0e2c7c9c6d5972aa4e90602001611453565b6114d2611b16565b8260035414611510576040517fd068bf5b00000000000000000000000000000000000000000000000000000000815260048101849052602401610ab2565b80511561155457827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d882604051611547919061311e565b60405180910390a2611945565b81516000036115bd57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516115479060208082526013908201527f456d70747920726573706f6e7365206461746100000000000000000000000000604082015260600190565b60208251101561164d57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d8604051611547906020808252602d908201527f4d616c666f726d656420726573706f6e73652064617461202d20696e7375666660408201527f696369656e74206c656e67746800000000000000000000000000000000000000606082015260800190565b815160201415801561166157508151604014155b156116ec57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516115479060208082526023908201527f496e76616c696420726573706f6e7365206c656e67746820666f722075696e7460408201527f3235360000000000000000000000000000000000000000000000000000000000606082015260800190565b6000828060200190518101906117029190613131565b9050806000036117a057837f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516117929060208082526021908201527f43616e6e6f74207570646174652077697468207a65726f204e41562076616c7560408201527f6500000000000000000000000000000000000000000000000000000000000000606082015260800190565b60405180910390a250611945565b60135460ff1680156117b457506000600454115b156118b15760006004548211156117d9576004546117d29083612f8e565b90506117ea565b816004546117e79190612f8e565b90505b6004546000906117fc83612710612fa1565b6118069190612fce565b90506012548111156118ae57600454604080518581526020810192909252810182905286907f87f1134414af80af3c021db7f09983bd44be06e21b368b608181833a9e6289999060600160405180910390a2600454604080518581526020810192909252810182905286907f6f51259805c57907419075f90a8ed881dacf57fb4f4bc42c9d88585d4fffe28a9060600160405180910390a26118a6611f18565b505050611945565b50505b6004805460065560058054600755908290554290556118cf81611b59565b837f80bd2b323e3a6af589795c93e573d2de859bdd53d085cdf5b68eb5edc750b6c28260405161190191815260200190565b60405180910390a2427f224bbf4ba043354bee6487d05aa90892db4426afe8e3aa79007d0eae1b985ebc8260405161193b91815260200190565b60405180910390a2505b610a0560018055565b610a3c8133611f55565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166119fa576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556119b23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610748565b506000610748565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156119fa576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610748565b611a8d611fc5565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60025460ff1615611b14576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600260015403611b52576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b60135461010090046001600160a01b031615610a3c576013546040517f16b60249000000000000000000000000000000000000000000000000000000008152600481018390526101009091046001600160a01b0316906316b6024990602401600060405180830381600087803b158015611bd257600080fd5b505af1925050508015611be3575060015b610a3c573d808015611c11576040519150601f19603f3d011682016040523d82523d6000602084013e611c16565b606091505b50601354604080518481526101009092046001600160a01b031660208301527fcc893a8b2c65b4d2b98d7ce00c3caf92cde0bf58c518a6cf746f792c1cf534c69101611453565b6000600a8054611c6c90612e27565b9050600003611c8e57604051631161b0b360e01b815260040160405180910390fd5b60095467ffffffffffffffff16600003611cbb57604051630ebd8d1960e11b815260040160405180910390fd5b600854611cdb576040516391f7443960e01b815260040160405180910390fd5b600954620186a06801000000000000000090910463ffffffff161015611d1957604051630298914960e41b8152620186a06004820152602401610ab2565b611d5a6040805160e0810190915280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b611df7600a8054611d6a90612e27565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9690612e27565b8015611de35780601f10611db857610100808354040283529160200191611de3565b820191906000526020600020905b815481529060010190602001808311611dc657829003601f168201915b50505050508261200190919063ffffffff16565b6000600b8054611e0690612e27565b90501115611eab57611eab600b8054611e1e90612e27565b80601f0160208091040260200160405190810160405280929190818152602001828054611e4a90612e27565b8015611e975780601f10611e6c57610100808354040283529160200191611e97565b820191906000526020600020905b815481529060010190602001808311611e7a57829003601f168201915b50505050508261200e90919063ffffffff16565b611ee1611eb782612058565b60095460085467ffffffffffffffff82169168010000000000000000900463ffffffff16906123c7565b600381905560405190925082907fe4a590f2aeb7a78489900321756fa3943a8ad762dcffc1daea08af7885afe91590600090a25090565b611f20611ad7565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611aba3390565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611fc1576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610ab2565b5050565b60025460ff16611b14576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fc18260008084612499565b8051600003612049576040517fe889636f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016020830152608090910152565b60606000612067610100612530565b90506120b16040518060400160405280600c81526020017f636f64654c6f636174696f6e00000000000000000000000000000000000000008152508261255190919063ffffffff16565b82516120cf9060028111156120c8576120c861314a565b829061256a565b60408051808201909152600881527f6c616e6775616765000000000000000000000000000000000000000000000000602082015261210e908290612551565b60408301516121259080156120c8576120c861314a565b60408051808201909152600681527f736f7572636500000000000000000000000000000000000000000000000000006020820152612164908290612551565b6060830151612174908290612551565b60a083015151156122195760408051808201909152600481527f617267730000000000000000000000000000000000000000000000000000000060208201526121be908290612551565b6121c7816125a3565b60005b8360a001515181101561220f576122078460a0015182815181106121f0576121f0613160565b60200260200101518361255190919063ffffffff16565b6001016121ca565b50612219816125c7565b6080830151511561231a5760008360200151600281111561223c5761223c61314a565b03612273576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e000000000000000000000000000000000060208201526122b2908290612551565b6122cb836020015160028111156120c8576120c861314a565b60408051808201909152600781527f7365637265747300000000000000000000000000000000000000000000000000602082015261230a908290612551565b608083015161231a9082906125e5565b60c083015151156123bf5760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152612364908290612551565b61236d816125a3565b60005b8360c00151518110156123b5576123ad8460c00151828151811061239657612396613160565b6020026020010151836125e590919063ffffffff16565b600101612370565b506123bf816125c7565b515192915050565b6000807f00000000000000000000000065dcc24f8ff9e51f10dcc7ed1e4e2a61e6e14bd66001600160a01b031663461d27628688600188886040518663ffffffff1660e01b815260040161241f959493929190613176565b6020604051808303816000875af115801561243e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124629190613131565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b80516000036124d4576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838360028111156124e7576124e761314a565b908160028111156124fa576124fa61314a565b905250604084018280156125105761251061314a565b908180156125205761252061314a565b9052506060909301929092525050565b61253861299f565b805161254490836125f2565b5060006020820152919050565b61255e8260038351612669565b8151610a05908261278a565b81516125779060c26127b2565b50611fc1828260405160200161258f91815260200190565b6040516020818303038152906040526125e5565b6125ae81600461281b565b6001816020018181516125c191906130d3565b90525050565b6125d281600761281b565b6001816020018181516125c19190612f8e565b61255e8260028351612669565b6040805180820190915260608152600060208201526126126020836130bf565b1561263a576126226020836130bf565b61262d906020612f8e565b61263790836130d3565b91505b60208084018390526040518085526000815290818401018181101561265e57600080fd5b604052509192915050565b60178167ffffffffffffffff16116126905782516109b39060e0600585901b1683176127b2565b60ff8167ffffffffffffffff16116126d25782516126b9906018611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166001612832565b61ffff8167ffffffffffffffff16116127155782516126fc906019611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166002612832565b63ffffffff8167ffffffffffffffff161161275a57825161274190601a611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166004612832565b825161277190601b611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166008612832565b6040805180820190915260608152600060208201526127ab838384516128b7565b9392505050565b60408051808201909152606081526000602082015282515160006127d78260016130d3565b9050846020015182106127f8576127f8856127f3836002612fa1565b612988565b8451602083820101858153508051821115612811578181525b5093949350505050565b8151610a0590601f611fe0600585901b16176127b2565b604080518082019091526060815260006020820152835151600061285682856130d3565b9050856020015181111561287357612873866127f3836002612fa1565b60006001612883866101006132a7565b61288d9190612f8e565b905086518281018783198251161781525080518311156128ab578281525b50959695505050505050565b60408051808201909152606081526000602082015282518211156128da57600080fd5b83515160006128e984836130d3565b9050856020015181111561290657612906866127f3836002612fa1565b855180518382016020019160009180851115612920578482525b505050602086015b60208610612960578051825261293f6020836130d3565b915061294c6020826130d3565b9050612959602087612f8e565b9550612928565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161299483836125f2565b506109b3838261278a565b60405180604001604052806129c7604051806040016040528060608152602001600081525090565b8152602001600081525090565b6000602082840312156129e657600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146127ab57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a5557612a55612a16565b604052919050565b600067ffffffffffffffff821115612a7757612a77612a16565b50601f01601f191660200190565b600082601f830112612a9657600080fd5b8135612aa9612aa482612a5d565b612a2c565b818152846020838601011115612abe57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215612af057600080fd5b83359250602084013567ffffffffffffffff811115612b0e57600080fd5b612b1a86828701612a85565b925050604084013567ffffffffffffffff811115612b3757600080fd5b612b4386828701612a85565b9150509250925092565b60008083601f840112612b5f57600080fd5b50813567ffffffffffffffff811115612b7757600080fd5b602083019150836020828501011115610ec157600080fd5b60008060008060008060808789031215612ba857600080fd5b863567ffffffffffffffff81168114612bc057600080fd5b955060208701359450604087013567ffffffffffffffff811115612be357600080fd5b612bef89828a01612b4d565b909550935050606087013567ffffffffffffffff811115612c0f57600080fd5b612c1b89828a01612b4d565b979a9699509497509295939492505050565b600060208284031215612c3f57600080fd5b5035919050565b80356001600160a01b0381168114612c5d57600080fd5b919050565b60008060408385031215612c7557600080fd5b82359150612c8560208401612c46565b90509250929050565b600080600060408486031215612ca357600080fd5b83359250602084013567ffffffffffffffff811115612cc157600080fd5b612ccd86828701612b4d565b9497909650939450505050565b60008060208385031215612ced57600080fd5b823567ffffffffffffffff811115612d0457600080fd5b612d1085828601612b4d565b90969095509350505050565b60005b83811015612d37578181015183820152602001612d1f565b50506000910152565b60008151808452612d58816020860160208601612d1c565b601f01601f19169290920160200192915050565b8215158152604060208201526000612d876040830184612d40565b949350505050565b8015158114610a3c57600080fd5b600060208284031215612daf57600080fd5b81356127ab81612d8f565b600080600060608486031215612dcf57600080fd5b505081359360208301359350604090920135919050565b600060208284031215612df857600080fd5b6127ab82612c46565b600060208284031215612e1357600080fd5b813563ffffffff811681146127ab57600080fd5b600181811c90821680612e3b57607f821691505b602082108103612e5b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a0557806000526020600020601f840160051c81016020851015612e885750805b601f840160051c820191505b81811015610d545760008155600101612e94565b67ffffffffffffffff831115612ec057612ec0612a16565b612ed483612ece8354612e27565b83612e61565b6000601f841160018114612f085760008515612ef05750838201355b600019600387901b1c1916600186901b178355610d54565b600083815260209020601f19861690835b82811015612f395786850135825560209485019460019092019101612f19565b5086821015612f565760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561074857610748612f78565b808202811582820484141761074857610748612f78565b634e487b7160e01b600052601260045260246000fd5b600082612fdd57612fdd612fb8565b500490565b85815284602082015260806040820152826080820152828460a0830137600060a08483010152600060a0601f19601f86011683010190506001600160a01b03831660608301529695505050505050565b6000806040838503121561304557600080fd5b825161305081612d8f565b602084015190925067ffffffffffffffff81111561306d57600080fd5b8301601f8101851361307e57600080fd5b805161308c612aa482612a5d565b8181528660208385010111156130a157600080fd5b6130b2826020830160208601612d1c565b8093505050509250929050565b6000826130ce576130ce612fb8565b500690565b8082018082111561074857610748612f78565b60007f8000000000000000000000000000000000000000000000000000000000000000820361311757613117612f78565b5060000390565b6020815260006127ab6020830184612d40565b60006020828403121561314357600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff8616815260a06020820152600061319960a0830187612d40565b61ffff9590951660408301525063ffffffff92909216606083015260809091015292915050565b6001815b60018411156131fb578085048111156131df576131df612f78565b60018416156131ed57908102905b60019390931c9280026131c4565b935093915050565b60008261321257506001610748565b8161321f57506000610748565b8160018114613235576002811461323f5761325b565b6001915050610748565b60ff84111561325057613250612f78565b50506001821b610748565b5060208310610133831016604e8410600b841016171561327e575081810a610748565b61328b60001984846131c0565b806000190482111561329f5761329f612f78565b029392505050565b60006127ab838361320356fea2646970667358221220829a2b129afa6fe6867c15d490662ae6316a3df107a01c2139fdfb9ad0fd384764736f6c634300081d0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":1000},"remappings":[]},"optimization_runs":1000,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x84d4eaeb10f9E57b67622f667C6c13E22fA4b2B6/","decoded_constructor_args":[["0x65Dcc24F8ff9e51F10DCc7Ed1e4e2A61e6E14bd6",{"internalType":"address","name":"router","type":"address"}],["0x6C15B25E9750Dccb698C1a4023f34015bFe57649",{"internalType":"address","name":"admin","type":"address"}],["0x6C15B25E9750Dccb698C1a4023f34015bFe57649",{"internalType":"address","name":"updater","type":"address"}],["0x6C15B25E9750Dccb698C1a4023f34015bFe57649",{"internalType":"address","name":"emergencyUpdater","type":"address"}]],"compiler_version":"0.8.29+commit.ab55807c","is_verified_via_verifier_alliance":false,"verified_at":"2025-05-28T23:47:08.355888Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60a06040526017600c55602d600d55610384600e5560118054600160ff1991821681179092556103e860125560138054909116909117905534801561004357600080fd5b506040516136893803806136898339810160408190526100629161032a565b6001600160a01b0384166080819052600180556002805460ff191690556100ba5760405163eac0d38960e01b81526020600482015260066024820152653937baba32b960d11b60448201526064015b60405180910390fd5b6001600160a01b0383166100f95760405163eac0d38960e01b815260206004820152600560248201526430b236b4b760d91b60448201526064016100b1565b6001600160a01b03821661013a5760405163eac0d38960e01b81526020600482015260076024820152663ab83230ba32b960c91b60448201526064016100b1565b6001600160a01b0381166101845760405163eac0d38960e01b815260206004820152601060248201526f32b6b2b933b2b731bcaab83230ba32b960811b60448201526064016100b1565b6009805463ffffffff60401b19166a0493e000000000000000001790556101ac600084610262565b506101d77fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177584610262565b506102027f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab83610262565b5061022d7f9d1945eeb09f3a9323e5f22a567caed248092672554a0b04901240709fb1347682610262565b506102587ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab84610262565b505050505061037e565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16610304576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556102bc3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610308565b5060005b92915050565b80516001600160a01b038116811461032557600080fd5b919050565b6000806000806080858703121561034057600080fd5b6103498561030e565b93506103576020860161030e565b92506103656040860161030e565b91506103736060860161030e565b905092959194509250565b6080516132e96103a06000396000818161075901526123cc01526132e96000f3fe608060405234801561001057600080fd5b506004361061030a5760003560e01c806375b238fc1161019c578063b3d03582116100ee578063dd3a9a1011610097578063f063aa3311610071578063f063aa3314610690578063f475877514610699578063f7ced0e7146106a257600080fd5b8063dd3a9a1014610668578063dddbc04914610670578063eb5f23a61461068357600080fd5b8063d547741f116100c8578063d547741f14610640578063d966a59414610653578063daf6bce41461066057600080fd5b8063b3d035821461060f578063cc6dfe791461062e578063d2f343c71461063757600080fd5b806391d1485411610150578063a217fddf1161012a578063a217fddf146105eb578063a4eb718c146105f3578063a66143821461060657600080fd5b806391d148541461058e5780639bdcaf59146105c55780639c66e162146105d857600080fd5b80638205bf6a116101815780638205bf6a146105745780638456cb591461057d5780638dbe7b9d1461058557600080fd5b806375b238fc1461053a57806379e666221461056157600080fd5b806336568abe1161026057806354e4d19a11610209578063693de592116101e3578063693de592146104ea5780636e04ff0d146104f2578063721be4221461051357600080fd5b806354e4d19a146104b95780635953de96146104c25780635c975abb146104df57600080fd5b8063424562131161023a578063424562131461046c5780634585e33b1461047f57806347e633801461049257600080fd5b806336568abe146104485780633ee7a7011461045b5780633f4ba83a1461046457600080fd5b80631d9ff6e4116102c25780632f2ff15d1161029c5780632f2ff15d146103ff578063313ce56714610412578063364bc15a1461042157600080fd5b80631d9ff6e4146103a3578063248a9ca3146103ac5780632c2f03e0146103cf57600080fd5b80630ca76175116102f35780630ca761751461036457806314f69ebe146103795780631aa46f591461038c57600080fd5b806301ffc9a71461030f57806309c1ba2e14610337575b600080fd5b61032261031d3660046129d4565b6106b5565b60405190151581526020015b60405180910390f35b60095461034b9067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032e565b610377610372366004612adb565b61074e565b005b610377610387366004612b8f565b6107eb565b61039560035481565b60405190815260200161032e565b61039560075481565b6103956103ba366004612c2d565b60009081526020819052604090206001015490565b6013546103e79061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161032e565b61037761040d366004612c62565b61098e565b6040516012815260200161032e565b6103957ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab81565b610377610456366004612c62565b6109b9565b61039560125481565b610377610a0a565b61037761047a366004612c8e565b610a3f565b61037761048d366004612cda565b610c20565b6103957f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab81565b61039561384081565b6104ca610d5b565b6040805192835260208301919091520161032e565b60025460ff16610322565b6104ca610d72565b610505610500366004612cda565b610d89565b60405161032e929190612d6c565b6103957f9d1945eeb09f3a9323e5f22a567caed248092672554a0b04901240709fb1347681565b6103957fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b61037761056f366004612d9d565b610ec8565b61039560055481565b610377610f3c565b61039560085481565b61032261059c366004612c62565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6103776105d3366004612dba565b610f6e565b6103776105e6366004612de6565b6110ab565b610395600081565b610377610601366004612e01565b61117f565b610395600c5481565b610619620186a081565b60405163ffffffff909116815260200161032e565b610395600f5481565b610395600e5481565b61037761064e366004612c62565b61124e565b6011546103229060ff1681565b610395611273565b61039561132b565b61037761067e366004612c2d565b6113be565b6013546103229060ff1681565b61039560105481565b610395600d5481565b6103776106b0366004612d9d565b61145f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061074857507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107b0576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107bb8383836114ca565b60405183907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756108158161194e565b8667ffffffffffffffff1660000361084057604051630ebd8d1960e11b815260040160405180910390fd5b8561085e576040516391f7443960e01b815260040160405180910390fd5b600084900361088057604051631161b0b360e01b815260040160405180910390fd5b60008290036108bb576040517f08974bc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff191667ffffffffffffffff89161790556008869055600a6108ea858783612ea8565b50600b6108f8838583612ea8565b506000858560405161090b929190612f68565b6040518091039020905060008484604051610927929190612f68565b6040805191829003822067ffffffffffffffff8c168352602083018b905290820184905260608201819052915033907fd0460bc9a3d662ffa248c53ead902bfc09de1660e8bf7e202467ba7d9c525b849060800160405180910390a2505050505050505050565b6000828152602081905260409020600101546109a98161194e565b6109b38383611958565b50505050565b6001600160a01b03811633146109fb576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a058282611a02565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610a348161194e565b610a3c611a85565b50565b610a47611ad7565b7f9d1945eeb09f3a9323e5f22a567caed248092672554a0b04901240709fb13476610a718161194e565b610a79611b16565b83600003610abb576040517fc0c148d4000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b600060105442610acb9190612f8e565b90506000601054118015610ae0575061384081105b15610b22576040517f29108fcd000000000000000000000000000000000000000000000000000000008152600481018290526138406024820152604401610ab2565b60045460009015610b785760006004548711610b4b5786600454610b469190612f8e565b610b58565b600454610b589088612f8e565b600454909150610b6a82612710612fa1565b610b749190612fce565b9150505b6004805460065560058054600755908790554290819055601055610b9b86611b59565b427f2d7f7ae13710a5fc7ea85533ac930ce3bb3317b7282af073f3645dd3e6a412f48783888833604051610bd3959493929190612fe2565b60405180910390a2427f224bbf4ba043354bee6487d05aa90892db4426afe8e3aa79007d0eae1b985ebc87604051610c0d91815260200190565b60405180910390a250506109b360018055565b610c28611ad7565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab610c528161194e565b6040517f6e04ff0d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201819052903090636e04ff0d90604401600060405180830381865afa158015610cb1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cd99190810190613032565b50905080610d13576040517fa37ddd2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42600f8190556040519081527f883e407cc0ae0d12f7a01c2fdc3bd21afa3181401fc985b413f52316341eabe89060200160405180910390a1610d54611c5d565b5050505050565b600080610d66611ad7565b50506006546007549091565b600080610d7d611ad7565b50506004546005549091565b60115460009060609060ff161580610da3575060025460ff165b15610dc05750506040805160208101909152600080825290610ec1565b426000610dd062015180836130bf565b90506000610de0610e1083612fce565b90506000603c610df2610e10856130bf565b610dfc9190612fce565b90506000600d54603c610e0f9190612fa1565b600c54610e1e90610e10612fa1565b610e2891906130d3565b90506000610e37603c866130bf565b610e4284603c612fa1565b610e4e86610e10612fa1565b610e5891906130d3565b610e6291906130d3565b90506000828210158015610e815750600e54610e7e90846130d3565b82105b9050600062011940600f5489610e979190612f8e565b119050818015610ea45750805b995060405180602001604052806000815250985050505050505050505b9250929050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610ef28161194e565b6011805460ff191683151590811790915560405190815233907f84ea38e2d33114764b52620adfd1efa8dbc74614c1e2cdb6b16c16ffb798a2c59060200160405180910390a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f668161194e565b610a3c611f18565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f988161194e565b60188410610fd2576040517f6bae8b6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c831061100c576040517f053c1f4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012c82108061101e57506138408210155b15611055576040517fb11cd48100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c849055600d839055600e82905560408051858152602081018590529081018390527f7ba3a5f107a3591b604d817104b45edf844cd83ed1b93401dc66c4ac37a5bad09060600160405180910390a150505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756110d58161194e565b6001600160a01b038216611115576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601380547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101006001600160a01b038516908102919091179091556040517fee26f3ffb0fd9f2274be5e2c82a9e710e999b2da7d338b2d662d2540b14cf1bb90600090a25050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756111a98161194e565b620186a063ffffffff831610156111d857604051630298914960e41b8152620186a06004820152602401610ab2565b6009805463ffffffff848116680100000000000000008181026bffffffff000000000000000019851617909455604080519490930490911680845260208401919091529133917fa33fca53ddda42966636288d60b6f6c9167d025c6e8e960f01cdd4a036932a76910160405180910390a2505050565b6000828152602081905260409020600101546112698161194e565b6109b38383611a02565b600061127d611ad7565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16806112e857503360009081527f738678fe42df6a4211eb7628ac9b056229141839eb4f4ef4cc249f1d36e8c921602052604090205460ff165b61131e576040517f9cf11bdb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611326611c5d565b905090565b6000611335611ad7565b6006546000036113455750600090565b60006006546004541015611368576004546006546113639190612f8e565b611378565b6006546004546113789190612f8e565b90506000600654826305f5e10061138f9190612fa1565b6113999190612fce565b905060065460045410156113b5576113b0816130e6565b6113b7565b805b9250505090565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756113e88161194e565b81600003611422576040517f5880a9f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60128290556040518281527f3f9ef5ed5d378ef819698e4b3c710d362f981f90087b428b7a1ee1e716d689d5906020015b60405180910390a15050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756114898161194e565b6013805460ff19168315159081179091556040519081527f4b3846e59e75439d5fd0202dae15523da9daacc4b91b1e0e2c7c9c6d5972aa4e90602001611453565b6114d2611b16565b8260035414611510576040517fd068bf5b00000000000000000000000000000000000000000000000000000000815260048101849052602401610ab2565b80511561155457827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d882604051611547919061311e565b60405180910390a2611945565b81516000036115bd57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516115479060208082526013908201527f456d70747920726573706f6e7365206461746100000000000000000000000000604082015260600190565b60208251101561164d57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d8604051611547906020808252602d908201527f4d616c666f726d656420726573706f6e73652064617461202d20696e7375666660408201527f696369656e74206c656e67746800000000000000000000000000000000000000606082015260800190565b815160201415801561166157508151604014155b156116ec57827f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516115479060208082526023908201527f496e76616c696420726573706f6e7365206c656e67746820666f722075696e7460408201527f3235360000000000000000000000000000000000000000000000000000000000606082015260800190565b6000828060200190518101906117029190613131565b9050806000036117a057837f427bedf194be24d8a151ec8cb762b5c8eae088b4f0c01e72a307cf5a51ade5d86040516117929060208082526021908201527f43616e6e6f74207570646174652077697468207a65726f204e41562076616c7560408201527f6500000000000000000000000000000000000000000000000000000000000000606082015260800190565b60405180910390a250611945565b60135460ff1680156117b457506000600454115b156118b15760006004548211156117d9576004546117d29083612f8e565b90506117ea565b816004546117e79190612f8e565b90505b6004546000906117fc83612710612fa1565b6118069190612fce565b90506012548111156118ae57600454604080518581526020810192909252810182905286907f87f1134414af80af3c021db7f09983bd44be06e21b368b608181833a9e6289999060600160405180910390a2600454604080518581526020810192909252810182905286907f6f51259805c57907419075f90a8ed881dacf57fb4f4bc42c9d88585d4fffe28a9060600160405180910390a26118a6611f18565b505050611945565b50505b6004805460065560058054600755908290554290556118cf81611b59565b837f80bd2b323e3a6af589795c93e573d2de859bdd53d085cdf5b68eb5edc750b6c28260405161190191815260200190565b60405180910390a2427f224bbf4ba043354bee6487d05aa90892db4426afe8e3aa79007d0eae1b985ebc8260405161193b91815260200190565b60405180910390a2505b610a0560018055565b610a3c8133611f55565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166119fa576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556119b23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610748565b506000610748565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156119fa576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610748565b611a8d611fc5565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60025460ff1615611b14576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600260015403611b52576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b60135461010090046001600160a01b031615610a3c576013546040517f16b60249000000000000000000000000000000000000000000000000000000008152600481018390526101009091046001600160a01b0316906316b6024990602401600060405180830381600087803b158015611bd257600080fd5b505af1925050508015611be3575060015b610a3c573d808015611c11576040519150601f19603f3d011682016040523d82523d6000602084013e611c16565b606091505b50601354604080518481526101009092046001600160a01b031660208301527fcc893a8b2c65b4d2b98d7ce00c3caf92cde0bf58c518a6cf746f792c1cf534c69101611453565b6000600a8054611c6c90612e27565b9050600003611c8e57604051631161b0b360e01b815260040160405180910390fd5b60095467ffffffffffffffff16600003611cbb57604051630ebd8d1960e11b815260040160405180910390fd5b600854611cdb576040516391f7443960e01b815260040160405180910390fd5b600954620186a06801000000000000000090910463ffffffff161015611d1957604051630298914960e41b8152620186a06004820152602401610ab2565b611d5a6040805160e0810190915280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b611df7600a8054611d6a90612e27565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9690612e27565b8015611de35780601f10611db857610100808354040283529160200191611de3565b820191906000526020600020905b815481529060010190602001808311611dc657829003601f168201915b50505050508261200190919063ffffffff16565b6000600b8054611e0690612e27565b90501115611eab57611eab600b8054611e1e90612e27565b80601f0160208091040260200160405190810160405280929190818152602001828054611e4a90612e27565b8015611e975780601f10611e6c57610100808354040283529160200191611e97565b820191906000526020600020905b815481529060010190602001808311611e7a57829003601f168201915b50505050508261200e90919063ffffffff16565b611ee1611eb782612058565b60095460085467ffffffffffffffff82169168010000000000000000900463ffffffff16906123c7565b600381905560405190925082907fe4a590f2aeb7a78489900321756fa3943a8ad762dcffc1daea08af7885afe91590600090a25090565b611f20611ad7565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611aba3390565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611fc1576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610ab2565b5050565b60025460ff16611b14576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fc18260008084612499565b8051600003612049576040517fe889636f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016020830152608090910152565b60606000612067610100612530565b90506120b16040518060400160405280600c81526020017f636f64654c6f636174696f6e00000000000000000000000000000000000000008152508261255190919063ffffffff16565b82516120cf9060028111156120c8576120c861314a565b829061256a565b60408051808201909152600881527f6c616e6775616765000000000000000000000000000000000000000000000000602082015261210e908290612551565b60408301516121259080156120c8576120c861314a565b60408051808201909152600681527f736f7572636500000000000000000000000000000000000000000000000000006020820152612164908290612551565b6060830151612174908290612551565b60a083015151156122195760408051808201909152600481527f617267730000000000000000000000000000000000000000000000000000000060208201526121be908290612551565b6121c7816125a3565b60005b8360a001515181101561220f576122078460a0015182815181106121f0576121f0613160565b60200260200101518361255190919063ffffffff16565b6001016121ca565b50612219816125c7565b6080830151511561231a5760008360200151600281111561223c5761223c61314a565b03612273576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e000000000000000000000000000000000060208201526122b2908290612551565b6122cb836020015160028111156120c8576120c861314a565b60408051808201909152600781527f7365637265747300000000000000000000000000000000000000000000000000602082015261230a908290612551565b608083015161231a9082906125e5565b60c083015151156123bf5760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152612364908290612551565b61236d816125a3565b60005b8360c00151518110156123b5576123ad8460c00151828151811061239657612396613160565b6020026020010151836125e590919063ffffffff16565b600101612370565b506123bf816125c7565b515192915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663461d27628688600188886040518663ffffffff1660e01b815260040161241f959493929190613176565b6020604051808303816000875af115801561243e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124629190613131565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b80516000036124d4576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838360028111156124e7576124e761314a565b908160028111156124fa576124fa61314a565b905250604084018280156125105761251061314a565b908180156125205761252061314a565b9052506060909301929092525050565b61253861299f565b805161254490836125f2565b5060006020820152919050565b61255e8260038351612669565b8151610a05908261278a565b81516125779060c26127b2565b50611fc1828260405160200161258f91815260200190565b6040516020818303038152906040526125e5565b6125ae81600461281b565b6001816020018181516125c191906130d3565b90525050565b6125d281600761281b565b6001816020018181516125c19190612f8e565b61255e8260028351612669565b6040805180820190915260608152600060208201526126126020836130bf565b1561263a576126226020836130bf565b61262d906020612f8e565b61263790836130d3565b91505b60208084018390526040518085526000815290818401018181101561265e57600080fd5b604052509192915050565b60178167ffffffffffffffff16116126905782516109b39060e0600585901b1683176127b2565b60ff8167ffffffffffffffff16116126d25782516126b9906018611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166001612832565b61ffff8167ffffffffffffffff16116127155782516126fc906019611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166002612832565b63ffffffff8167ffffffffffffffff161161275a57825161274190601a611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166004612832565b825161277190601b611fe0600586901b16176127b2565b5082516109b39067ffffffffffffffff83166008612832565b6040805180820190915260608152600060208201526127ab838384516128b7565b9392505050565b60408051808201909152606081526000602082015282515160006127d78260016130d3565b9050846020015182106127f8576127f8856127f3836002612fa1565b612988565b8451602083820101858153508051821115612811578181525b5093949350505050565b8151610a0590601f611fe0600585901b16176127b2565b604080518082019091526060815260006020820152835151600061285682856130d3565b9050856020015181111561287357612873866127f3836002612fa1565b60006001612883866101006132a7565b61288d9190612f8e565b905086518281018783198251161781525080518311156128ab578281525b50959695505050505050565b60408051808201909152606081526000602082015282518211156128da57600080fd5b83515160006128e984836130d3565b9050856020015181111561290657612906866127f3836002612fa1565b855180518382016020019160009180851115612920578482525b505050602086015b60208610612960578051825261293f6020836130d3565b915061294c6020826130d3565b9050612959602087612f8e565b9550612928565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161299483836125f2565b506109b3838261278a565b60405180604001604052806129c7604051806040016040528060608152602001600081525090565b8152602001600081525090565b6000602082840312156129e657600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146127ab57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a5557612a55612a16565b604052919050565b600067ffffffffffffffff821115612a7757612a77612a16565b50601f01601f191660200190565b600082601f830112612a9657600080fd5b8135612aa9612aa482612a5d565b612a2c565b818152846020838601011115612abe57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215612af057600080fd5b83359250602084013567ffffffffffffffff811115612b0e57600080fd5b612b1a86828701612a85565b925050604084013567ffffffffffffffff811115612b3757600080fd5b612b4386828701612a85565b9150509250925092565b60008083601f840112612b5f57600080fd5b50813567ffffffffffffffff811115612b7757600080fd5b602083019150836020828501011115610ec157600080fd5b60008060008060008060808789031215612ba857600080fd5b863567ffffffffffffffff81168114612bc057600080fd5b955060208701359450604087013567ffffffffffffffff811115612be357600080fd5b612bef89828a01612b4d565b909550935050606087013567ffffffffffffffff811115612c0f57600080fd5b612c1b89828a01612b4d565b979a9699509497509295939492505050565b600060208284031215612c3f57600080fd5b5035919050565b80356001600160a01b0381168114612c5d57600080fd5b919050565b60008060408385031215612c7557600080fd5b82359150612c8560208401612c46565b90509250929050565b600080600060408486031215612ca357600080fd5b83359250602084013567ffffffffffffffff811115612cc157600080fd5b612ccd86828701612b4d565b9497909650939450505050565b60008060208385031215612ced57600080fd5b823567ffffffffffffffff811115612d0457600080fd5b612d1085828601612b4d565b90969095509350505050565b60005b83811015612d37578181015183820152602001612d1f565b50506000910152565b60008151808452612d58816020860160208601612d1c565b601f01601f19169290920160200192915050565b8215158152604060208201526000612d876040830184612d40565b949350505050565b8015158114610a3c57600080fd5b600060208284031215612daf57600080fd5b81356127ab81612d8f565b600080600060608486031215612dcf57600080fd5b505081359360208301359350604090920135919050565b600060208284031215612df857600080fd5b6127ab82612c46565b600060208284031215612e1357600080fd5b813563ffffffff811681146127ab57600080fd5b600181811c90821680612e3b57607f821691505b602082108103612e5b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a0557806000526020600020601f840160051c81016020851015612e885750805b601f840160051c820191505b81811015610d545760008155600101612e94565b67ffffffffffffffff831115612ec057612ec0612a16565b612ed483612ece8354612e27565b83612e61565b6000601f841160018114612f085760008515612ef05750838201355b600019600387901b1c1916600186901b178355610d54565b600083815260209020601f19861690835b82811015612f395786850135825560209485019460019092019101612f19565b5086821015612f565760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561074857610748612f78565b808202811582820484141761074857610748612f78565b634e487b7160e01b600052601260045260246000fd5b600082612fdd57612fdd612fb8565b500490565b85815284602082015260806040820152826080820152828460a0830137600060a08483010152600060a0601f19601f86011683010190506001600160a01b03831660608301529695505050505050565b6000806040838503121561304557600080fd5b825161305081612d8f565b602084015190925067ffffffffffffffff81111561306d57600080fd5b8301601f8101851361307e57600080fd5b805161308c612aa482612a5d565b8181528660208385010111156130a157600080fd5b6130b2826020830160208601612d1c565b8093505050509250929050565b6000826130ce576130ce612fb8565b500690565b8082018082111561074857610748612f78565b60007f8000000000000000000000000000000000000000000000000000000000000000820361311757613117612f78565b5060000390565b6020815260006127ab6020830184612d40565b60006020828403121561314357600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff8616815260a06020820152600061319960a0830187612d40565b61ffff9590951660408301525063ffffffff92909216606083015260809091015292915050565b6001815b60018411156131fb578085048111156131df576131df612f78565b60018416156131ed57908102905b60019390931c9280026131c4565b935093915050565b60008261321257506001610748565b8161321f57506000610748565b8160018114613235576002811461323f5761325b565b6001915050610748565b60ff84111561325057613250612f78565b50506001821b610748565b5060208310610133831016604e8410600b841016171561327e575081810a610748565b61328b60001984846131c0565b806000190482111561329f5761329f612f78565b029392505050565b60006127ab838361320356fea2646970667358221220829a2b129afa6fe6867c15d490662ae6316a3df107a01c2139fdfb9ad0fd384764736f6c634300081d003300000000000000000000000065dcc24f8ff9e51f10dcc7ed1e4e2a61e6e14bd60000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe576490000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe576490000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe57649","name":"NAVConsumer","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"@chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable-next-line interface-starts-with-i\ninterface AutomationCompatibleInterface {\n  /**\n   * @notice method that is simulated by the keepers to see if any work actually\n   * needs to be performed. This method does does not actually need to be\n   * executable, and since it is only ever simulated it can consume lots of gas.\n   * @dev To ensure that it is never called, you may want to add the\n   * cannotExecute modifier from KeeperBase to your implementation of this\n   * method.\n   * @param checkData specified in the upkeep registration so it is always the\n   * same for a registered upkeep. This can easily be broken down into specific\n   * arguments using `abi.decode`, so multiple upkeeps can be registered on the\n   * same contract and easily differentiated by the contract.\n   * @return upkeepNeeded boolean to indicate whether the keeper should call\n   * performUpkeep or not.\n   * @return performData bytes that the keeper should call performUpkeep with, if\n   * upkeep is needed. If you would like to encode data to decode later, try\n   * `abi.encode`.\n   */\n  function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);\n\n  /**\n   * @notice method that is actually executed by the keepers, via the registry.\n   * The data returned by the checkUpkeep simulation will be passed into\n   * this method to actually be executed.\n   * @dev The input to this method should not be trusted, and the caller of the\n   * method should not even be restricted to any single registry. Anyone should\n   * be able call it, and the input should be validated, there is no guarantee\n   * that the data passed in is the performData returned from checkUpkeep. This\n   * could happen due to malicious keepers, racing keepers, or simply a state\n   * change while the performUpkeep transaction is waiting for confirmation.\n   * Always validate the data passed in.\n   * @param performData is the data which was passed back from the checkData\n   * simulation. If it is encoded, it can easily be decoded into other types by\n   * calling `abi.decode`. This data should not be trusted, and should be\n   * validated against the contract's current state.\n   */\n  function performUpkeep(bytes calldata performData) external;\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {IFunctionsRouter} from \"./interfaces/IFunctionsRouter.sol\";\nimport {IFunctionsClient} from \"./interfaces/IFunctionsClient.sol\";\n\nimport {FunctionsRequest} from \"./libraries/FunctionsRequest.sol\";\n\n/// @title The Chainlink Functions client contract\n/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests\nabstract contract FunctionsClient is IFunctionsClient {\n  using FunctionsRequest for FunctionsRequest.Request;\n\n  IFunctionsRouter internal immutable i_router;\n\n  event RequestSent(bytes32 indexed id);\n  event RequestFulfilled(bytes32 indexed id);\n\n  error OnlyRouterCanFulfill();\n\n  constructor(address router) {\n    i_router = IFunctionsRouter(router);\n  }\n\n  /// @notice Sends a Chainlink Functions request\n  /// @param data The CBOR encoded bytes data for a Functions request\n  /// @param subscriptionId The subscription ID that will be charged to service the request\n  /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback\n  /// @return requestId The generated request ID for this request\n  function _sendRequest(\n    bytes memory data,\n    uint64 subscriptionId,\n    uint32 callbackGasLimit,\n    bytes32 donId\n  ) internal returns (bytes32) {\n    bytes32 requestId = i_router.sendRequest(\n      subscriptionId,\n      data,\n      FunctionsRequest.REQUEST_DATA_VERSION,\n      callbackGasLimit,\n      donId\n    );\n    emit RequestSent(requestId);\n    return requestId;\n  }\n\n  /// @notice User defined function to handle a response from the DON\n  /// @param requestId The request ID, returned by sendRequest()\n  /// @param response Aggregated response from the execution of the user's source code\n  /// @param err Aggregated error from the execution of the user code or from the execution pipeline\n  /// @dev Either response or error parameter will be set, but never both\n  function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual;\n\n  /// @inheritdoc IFunctionsClient\n  function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override {\n    if (msg.sender != address(i_router)) {\n      revert OnlyRouterCanFulfill();\n    }\n    fulfillRequest(requestId, response, err);\n    emit RequestFulfilled(requestId);\n  }\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/// @title Chainlink Functions client interface.\ninterface IFunctionsClient {\n  /// @notice Chainlink Functions response handler called by the Functions Router\n  /// during fullilment from the designated transmitter node in an OCR round.\n  /// @param requestId The requestId returned by FunctionsClient.sendRequest().\n  /// @param response Aggregated response from the request's source code.\n  /// @param err Aggregated error either from the request's source code or from the execution pipeline.\n  /// @dev Either response or error parameter will be set, but never both.\n  function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external;\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {FunctionsResponse} from \"../libraries/FunctionsResponse.sol\";\n\n/// @title Chainlink Functions Router interface.\ninterface IFunctionsRouter {\n  /// @notice The identifier of the route to retrieve the address of the access control contract\n  /// The access control contract controls which accounts can manage subscriptions\n  /// @return id - bytes32 id that can be passed to the \"getContractById\" of the Router\n  function getAllowListId() external view returns (bytes32);\n\n  /// @notice Set the identifier of the route to retrieve the address of the access control contract\n  /// The access control contract controls which accounts can manage subscriptions\n  function setAllowListId(bytes32 allowListId) external;\n\n  /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network\n  /// @return adminFee\n  function getAdminFee() external view returns (uint72 adminFee);\n\n  /// @notice Sends a request using the provided subscriptionId\n  /// @param subscriptionId - A unique subscription ID allocated by billing system,\n  /// a client can make requests from different contracts referencing the same subscription\n  /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request\n  /// @param dataVersion - Gas limit for the fulfillment callback\n  /// @param callbackGasLimit - Gas limit for the fulfillment callback\n  /// @param donId - An identifier used to determine which route to send the request along\n  /// @return requestId - A unique request identifier\n  function sendRequest(\n    uint64 subscriptionId,\n    bytes calldata data,\n    uint16 dataVersion,\n    uint32 callbackGasLimit,\n    bytes32 donId\n  ) external returns (bytes32);\n\n  /// @notice Sends a request to the proposed contracts\n  /// @param subscriptionId - A unique subscription ID allocated by billing system,\n  /// a client can make requests from different contracts referencing the same subscription\n  /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request\n  /// @param dataVersion - Gas limit for the fulfillment callback\n  /// @param callbackGasLimit - Gas limit for the fulfillment callback\n  /// @param donId - An identifier used to determine which route to send the request along\n  /// @return requestId - A unique request identifier\n  function sendRequestToProposed(\n    uint64 subscriptionId,\n    bytes calldata data,\n    uint16 dataVersion,\n    uint32 callbackGasLimit,\n    bytes32 donId\n  ) external returns (bytes32);\n\n  /// @notice Fulfill the request by:\n  /// - calling back the data that the Oracle returned to the client contract\n  /// - pay the DON for processing the request\n  /// @dev Only callable by the Coordinator contract that is saved in the commitment\n  /// @param response response data from DON consensus\n  /// @param err error from DON consensus\n  /// @param juelsPerGas - current rate of juels/gas\n  /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment\n  /// @param transmitter - The Node that transmitted the OCR report\n  /// @param commitment - The parameters of the request that must be held consistent between request and response time\n  /// @return fulfillResult -\n  /// @return callbackGasCostJuels -\n  function fulfill(\n    bytes memory response,\n    bytes memory err,\n    uint96 juelsPerGas,\n    uint96 costWithoutFulfillment,\n    address transmitter,\n    FunctionsResponse.Commitment memory commitment\n  ) external returns (FunctionsResponse.FulfillResult, uint96);\n\n  /// @notice Validate requested gas limit is below the subscription max.\n  /// @param subscriptionId subscription ID\n  /// @param callbackGasLimit desired callback gas limit\n  function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view;\n\n  /// @notice Get the current contract given an ID\n  /// @param id A bytes32 identifier for the route\n  /// @return contract The current contract address\n  function getContractById(bytes32 id) external view returns (address);\n\n  /// @notice Get the proposed next contract given an ID\n  /// @param id A bytes32 identifier for the route\n  /// @return contract The current or proposed contract address\n  function getProposedContractById(bytes32 id) external view returns (address);\n\n  /// @notice Return the latest proprosal set\n  /// @return ids The identifiers of the contracts to update\n  /// @return to The addresses of the contracts that will be updated to\n  function getProposedContractSet() external view returns (bytes32[] memory, address[] memory);\n\n  /// @notice Proposes one or more updates to the contract routes\n  /// @dev Only callable by owner\n  function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external;\n\n  /// @notice Updates the current contract routes to the proposed contracts\n  /// @dev Only callable by owner\n  function updateContracts() external;\n\n  /// @dev Puts the system into an emergency stopped state.\n  /// @dev Only callable by owner\n  function pause() external;\n\n  /// @dev Takes the system out of an emergency stopped state.\n  /// @dev Only callable by owner\n  function unpause() external;\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {CBOR} from \"../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol\";\n\n/// @title Library for encoding the input data of a Functions request into CBOR\nlibrary FunctionsRequest {\n  using CBOR for CBOR.CBORBuffer;\n\n  uint16 public constant REQUEST_DATA_VERSION = 1;\n  uint256 internal constant DEFAULT_BUFFER_SIZE = 256;\n\n  enum Location {\n    Inline, // Provided within the Request\n    Remote, // Hosted through remote location that can be accessed through a provided URL\n    DONHosted // Hosted on the DON's storage\n  }\n\n  enum CodeLanguage {\n    JavaScript\n    // In future version we may add other languages\n  }\n\n  struct Request {\n    Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON\n    Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported\n    CodeLanguage language; // ════════════╸ The coding language that the source code is written in\n    string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted\n    bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets())\n    string[] args; // ════════════════════╸ String arguments that will be passed into the source code\n    bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code\n  }\n\n  error EmptySource();\n  error EmptySecrets();\n  error EmptyArgs();\n  error NoInlineSecrets();\n\n  /// @notice Encodes a Request to CBOR encoded bytes\n  /// @param self The request to encode\n  /// @return CBOR encoded bytes\n  function encodeCBOR(Request memory self) internal pure returns (bytes memory) {\n    CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE);\n\n    buffer.writeString(\"codeLocation\");\n    buffer.writeUInt256(uint256(self.codeLocation));\n\n    buffer.writeString(\"language\");\n    buffer.writeUInt256(uint256(self.language));\n\n    buffer.writeString(\"source\");\n    buffer.writeString(self.source);\n\n    if (self.args.length > 0) {\n      buffer.writeString(\"args\");\n      buffer.startArray();\n      for (uint256 i = 0; i < self.args.length; ++i) {\n        buffer.writeString(self.args[i]);\n      }\n      buffer.endSequence();\n    }\n\n    if (self.encryptedSecretsReference.length > 0) {\n      if (self.secretsLocation == Location.Inline) {\n        revert NoInlineSecrets();\n      }\n      buffer.writeString(\"secretsLocation\");\n      buffer.writeUInt256(uint256(self.secretsLocation));\n      buffer.writeString(\"secrets\");\n      buffer.writeBytes(self.encryptedSecretsReference);\n    }\n\n    if (self.bytesArgs.length > 0) {\n      buffer.writeString(\"bytesArgs\");\n      buffer.startArray();\n      for (uint256 i = 0; i < self.bytesArgs.length; ++i) {\n        buffer.writeBytes(self.bytesArgs[i]);\n      }\n      buffer.endSequence();\n    }\n\n    return buffer.buf.buf;\n  }\n\n  /// @notice Initializes a Chainlink Functions Request\n  /// @dev Sets the codeLocation and code on the request\n  /// @param self The uninitialized request\n  /// @param codeLocation The user provided source code location\n  /// @param language The programming language of the user code\n  /// @param source The user provided source code or a url\n  function initializeRequest(\n    Request memory self,\n    Location codeLocation,\n    CodeLanguage language,\n    string memory source\n  ) internal pure {\n    if (bytes(source).length == 0) revert EmptySource();\n\n    self.codeLocation = codeLocation;\n    self.language = language;\n    self.source = source;\n  }\n\n  /// @notice Initializes a Chainlink Functions Request\n  /// @dev Simplified version of initializeRequest for PoC\n  /// @param self The uninitialized request\n  /// @param javaScriptSource The user provided JS code (must not be empty)\n  function initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure {\n    initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource);\n  }\n\n  /// @notice Adds Remote user encrypted secrets to a Request\n  /// @param self The initialized request\n  /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets\n  function addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure {\n    if (encryptedSecretsReference.length == 0) revert EmptySecrets();\n\n    self.secretsLocation = Location.Remote;\n    self.encryptedSecretsReference = encryptedSecretsReference;\n  }\n\n  /// @notice Adds DON-hosted secrets reference to a Request\n  /// @param self The initialized request\n  /// @param slotID Slot ID of the user's secrets hosted on DON\n  /// @param version User data version (for the slotID)\n  function addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure {\n    CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE);\n\n    buffer.writeString(\"slotID\");\n    buffer.writeUInt64(slotID);\n    buffer.writeString(\"version\");\n    buffer.writeUInt64(version);\n\n    self.secretsLocation = Location.DONHosted;\n    self.encryptedSecretsReference = buffer.buf.buf;\n  }\n\n  /// @notice Sets args for the user run function\n  /// @param self The initialized request\n  /// @param args The array of string args (must not be empty)\n  function setArgs(Request memory self, string[] memory args) internal pure {\n    if (args.length == 0) revert EmptyArgs();\n\n    self.args = args;\n  }\n\n  /// @notice Sets bytes args for the user run function\n  /// @param self The initialized request\n  /// @param args The array of bytes args (must not be empty)\n  function setBytesArgs(Request memory self, bytes[] memory args) internal pure {\n    if (args.length == 0) revert EmptyArgs();\n\n    self.bytesArgs = args;\n  }\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/// @title Library of types that are used for fulfillment of a Functions request\nlibrary FunctionsResponse {\n  // Used to send request information from the Router to the Coordinator\n  struct RequestMeta {\n    bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request\n    bytes32 flags; // ═══════════════╸ Per-subscription flags\n    address requestingContract; // ══╗ The client contract that is sending the request\n    uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests.\n    uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network\n    uint64 subscriptionId; //        ║ Identifier of the billing subscription that will be charged for the request\n    uint64 initiatedRequests; //     ║ The number of requests that have been started\n    uint32 callbackGasLimit; //      ║ The amount of gas that the callback to the consuming contract will be given\n    uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data\n    uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out\n    address subscriptionOwner; // ═══╝ The owner of the billing subscription\n  }\n\n  enum FulfillResult {\n    FULFILLED, // 0\n    USER_CALLBACK_ERROR, // 1\n    INVALID_REQUEST_ID, // 2\n    COST_EXCEEDS_COMMITMENT, // 3\n    INSUFFICIENT_GAS_PROVIDED, // 4\n    SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5\n    INVALID_COMMITMENT // 6\n  }\n\n  struct Commitment {\n    bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request\n    address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request\n    uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request\n    address client; // ════════════════════╗ The client contract that sent the request\n    uint64 subscriptionId; //              ║ Identifier of the billing subscription that will be charged for the request\n    uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given\n    uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network\n    uint72 donFee; //                      ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request\n    uint40 gasOverheadBeforeCallback; //   ║ Represents the average gas execution cost before the fulfillment callback.\n    uint40 gasOverheadAfterCallback; //    ║ Represents the average gas execution cost after the fulfillment callback.\n    uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out\n  }\n}\n"},{"file_path":"@chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol","source_code":"// SPDX-License-Identifier: BSD-2-Clause\npragma solidity ^0.8.4;\n\n/**\n* @dev A library for working with mutable byte buffers in Solidity.\n*\n* Byte buffers are mutable and expandable, and provide a variety of primitives\n* for appending to them. At any time you can fetch a bytes object containing the\n* current contents of the buffer. The bytes object should not be stored between\n* operations, as it may change due to resizing of the buffer.\n*/\nlibrary Buffer {\n    /**\n    * @dev Represents a mutable buffer. Buffers have a current value (buf) and\n    *      a capacity. The capacity may be longer than the current value, in\n    *      which case it can be extended without the need to allocate more memory.\n    */\n    struct buffer {\n        bytes buf;\n        uint capacity;\n    }\n\n    /**\n    * @dev Initializes a buffer with an initial capacity.\n    * @param buf The buffer to initialize.\n    * @param capacity The number of bytes of space to allocate the buffer.\n    * @return The buffer, for chaining.\n    */\n    function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\n        if (capacity % 32 != 0) {\n            capacity += 32 - (capacity % 32);\n        }\n        // Allocate space for the buffer data\n        buf.capacity = capacity;\n        assembly {\n            let ptr := mload(0x40)\n            mstore(buf, ptr)\n            mstore(ptr, 0)\n            let fpm := add(32, add(ptr, capacity))\n            if lt(fpm, ptr) {\n                revert(0, 0)\n            }\n            mstore(0x40, fpm)\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Initializes a new buffer from an existing bytes object.\n    *      Changes to the buffer may mutate the original value.\n    * @param b The bytes object to initialize the buffer with.\n    * @return A new buffer.\n    */\n    function fromBytes(bytes memory b) internal pure returns(buffer memory) {\n        buffer memory buf;\n        buf.buf = b;\n        buf.capacity = b.length;\n        return buf;\n    }\n\n    function resize(buffer memory buf, uint capacity) private pure {\n        bytes memory oldbuf = buf.buf;\n        init(buf, capacity);\n        append(buf, oldbuf);\n    }\n\n    /**\n    * @dev Sets buffer length to 0.\n    * @param buf The buffer to truncate.\n    * @return The original buffer, for chaining..\n    */\n    function truncate(buffer memory buf) internal pure returns (buffer memory) {\n        assembly {\n            let bufptr := mload(buf)\n            mstore(bufptr, 0)\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @param len The number of bytes to copy.\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\n        require(len <= data.length);\n\n        uint off = buf.buf.length;\n        uint newCapacity = off + len;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        uint dest;\n        uint src;\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Length of existing buffer data\n            let buflen := mload(bufptr)\n            // Start address = buffer address + offset + sizeof(buffer length)\n            dest := add(add(bufptr, 32), off)\n            // Update buffer length if we're extending it\n            if gt(newCapacity, buflen) {\n                mstore(bufptr, newCapacity)\n            }\n            src := add(data, 32)\n        }\n\n        // Copy word-length chunks while possible\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        // Copy remaining bytes\n        unchecked {\n            uint mask = (256 ** (32 - len)) - 1;\n            assembly {\n                let srcpart := and(mload(src), not(mask))\n                let destpart := and(mload(dest), mask)\n                mstore(dest, or(destpart, srcpart))\n            }\n        }\n\n        return buf;\n    }\n\n    /**\n    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\n        return append(buf, data, data.length);\n    }\n\n    /**\n    * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\n    *      capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint offPlusOne = off + 1;\n        if (off >= buf.capacity) {\n            resize(buf, offPlusOne * 2);\n        }\n\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Address = buffer address + sizeof(buffer length) + off\n            let dest := add(add(bufptr, off), 32)\n            mstore8(dest, data)\n            // Update buffer length if we extended it\n            if gt(offPlusOne, mload(bufptr)) {\n                mstore(bufptr, offPlusOne)\n            }\n        }\n\n        return buf;\n    }\n\n    /**\n    * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\n    *      exceed the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @param len The number of bytes to write (left-aligned).\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint newCapacity = len + off;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        unchecked {\n            uint mask = (256 ** len) - 1;\n            // Right-align data\n            data = data >> (8 * (32 - len));\n            assembly {\n                // Memory address of the buffer data\n                let bufptr := mload(buf)\n                // Address = buffer address + sizeof(buffer length) + newCapacity\n                let dest := add(bufptr, newCapacity)\n                mstore(dest, or(and(mload(dest), not(mask)), data))\n                // Update buffer length if we extended it\n                if gt(newCapacity, mload(bufptr)) {\n                    mstore(bufptr, newCapacity)\n                }\n            }\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chhaining.\n    */\n    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\n        return append(buf, bytes32(data), 20);\n    }\n\n    /**\n    * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\n        return append(buf, data, 32);\n    }\n\n    /**\n     * @dev Appends a byte to the end of the buffer. Resizes if doing so would\n     *      exceed the capacity of the buffer.\n     * @param buf The buffer to append to.\n     * @param data The data to append.\n     * @param len The number of bytes to write (right-aligned).\n     * @return The original buffer.\n     */\n    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint newCapacity = len + off;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        uint mask = (256 ** len) - 1;\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Address = buffer address + sizeof(buffer length) + newCapacity\n            let dest := add(bufptr, newCapacity)\n            mstore(dest, or(and(mload(dest), not(mask)), data))\n            // Update buffer length if we extended it\n            if gt(newCapacity, mload(bufptr)) {\n                mstore(bufptr, newCapacity)\n            }\n        }\n        return buf;\n    }\n}"},{"file_path":"@chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../../@ensdomains/buffer/v0.1.0/Buffer.sol\";\n\n/**\n* @dev A library for populating CBOR encoded payload in Solidity.\n*\n* https://datatracker.ietf.org/doc/html/rfc7049\n*\n* The library offers various write* and start* methods to encode values of different types.\n* The resulted buffer can be obtained with data() method.\n* Encoding of primitive types is staightforward, whereas encoding of sequences can result\n* in an invalid CBOR if start/write/end flow is violated.\n* For the purpose of gas saving, the library does not verify start/write/end flow internally,\n* except for nested start/end pairs.\n*/\n\nlibrary CBOR {\n    using Buffer for Buffer.buffer;\n\n    struct CBORBuffer {\n        Buffer.buffer buf;\n        uint256 depth;\n    }\n\n    uint8 private constant MAJOR_TYPE_INT = 0;\n    uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;\n    uint8 private constant MAJOR_TYPE_BYTES = 2;\n    uint8 private constant MAJOR_TYPE_STRING = 3;\n    uint8 private constant MAJOR_TYPE_ARRAY = 4;\n    uint8 private constant MAJOR_TYPE_MAP = 5;\n    uint8 private constant MAJOR_TYPE_TAG = 6;\n    uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;\n\n    uint8 private constant TAG_TYPE_BIGNUM = 2;\n    uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3;\n\n    uint8 private constant CBOR_FALSE = 20;\n    uint8 private constant CBOR_TRUE = 21;\n    uint8 private constant CBOR_NULL = 22;\n    uint8 private constant CBOR_UNDEFINED = 23;\n\n    function create(uint256 capacity) internal pure returns(CBORBuffer memory cbor) {\n        Buffer.init(cbor.buf, capacity);\n        cbor.depth = 0;\n        return cbor;\n    }\n\n    function data(CBORBuffer memory buf) internal pure returns(bytes memory) {\n        require(buf.depth == 0, \"Invalid CBOR\");\n        return buf.buf.buf;\n    }\n\n    function writeUInt256(CBORBuffer memory buf, uint256 value) internal pure {\n        buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM));\n        writeBytes(buf, abi.encode(value));\n    }\n\n    function writeInt256(CBORBuffer memory buf, int256 value) internal pure {\n        if (value < 0) {\n            buf.buf.appendUint8(\n                uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)\n            );\n            writeBytes(buf, abi.encode(uint256(-1 - value)));\n        } else {\n            writeUInt256(buf, uint256(value));\n        }\n    }\n\n    function writeUInt64(CBORBuffer memory buf, uint64 value) internal pure {\n        writeFixedNumeric(buf, MAJOR_TYPE_INT, value);\n    }\n\n    function writeInt64(CBORBuffer memory buf, int64 value) internal pure {\n        if(value >= 0) {\n            writeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value));\n        } else{\n            writeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value));\n        }\n    }\n\n    function writeBytes(CBORBuffer memory buf, bytes memory value) internal pure {\n        writeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length));\n        buf.buf.append(value);\n    }\n\n    function writeString(CBORBuffer memory buf, string memory value) internal pure {\n        writeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length));\n        buf.buf.append(bytes(value));\n    }\n\n    function writeBool(CBORBuffer memory buf, bool value) internal pure {\n        writeContentFree(buf, value ? CBOR_TRUE : CBOR_FALSE);\n    }\n\n    function writeNull(CBORBuffer memory buf) internal pure {\n        writeContentFree(buf, CBOR_NULL);\n    }\n\n    function writeUndefined(CBORBuffer memory buf) internal pure {\n        writeContentFree(buf, CBOR_UNDEFINED);\n    }\n\n    function startArray(CBORBuffer memory buf) internal pure {\n        writeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);\n        buf.depth += 1;\n    }\n\n    function startFixedArray(CBORBuffer memory buf, uint64 length) internal pure {\n        writeDefiniteLengthType(buf, MAJOR_TYPE_ARRAY, length);\n    }\n\n    function startMap(CBORBuffer memory buf) internal pure {\n        writeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);\n        buf.depth += 1;\n    }\n\n    function startFixedMap(CBORBuffer memory buf, uint64 length) internal pure {\n        writeDefiniteLengthType(buf, MAJOR_TYPE_MAP, length);\n    }\n\n    function endSequence(CBORBuffer memory buf) internal pure {\n        writeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);\n        buf.depth -= 1;\n    }\n\n    function writeKVString(CBORBuffer memory buf, string memory key, string memory value) internal pure {\n        writeString(buf, key);\n        writeString(buf, value);\n    }\n\n    function writeKVBytes(CBORBuffer memory buf, string memory key, bytes memory value) internal pure {\n        writeString(buf, key);\n        writeBytes(buf, value);\n    }\n\n    function writeKVUInt256(CBORBuffer memory buf, string memory key, uint256 value) internal pure {\n        writeString(buf, key);\n        writeUInt256(buf, value);\n    }\n\n    function writeKVInt256(CBORBuffer memory buf, string memory key, int256 value) internal pure {\n        writeString(buf, key);\n        writeInt256(buf, value);\n    }\n\n    function writeKVUInt64(CBORBuffer memory buf, string memory key, uint64 value) internal pure {\n        writeString(buf, key);\n        writeUInt64(buf, value);\n    }\n\n    function writeKVInt64(CBORBuffer memory buf, string memory key, int64 value) internal pure {\n        writeString(buf, key);\n        writeInt64(buf, value);\n    }\n\n    function writeKVBool(CBORBuffer memory buf, string memory key, bool value) internal pure {\n        writeString(buf, key);\n        writeBool(buf, value);\n    }\n\n    function writeKVNull(CBORBuffer memory buf, string memory key) internal pure {\n        writeString(buf, key);\n        writeNull(buf);\n    }\n\n    function writeKVUndefined(CBORBuffer memory buf, string memory key) internal pure {\n        writeString(buf, key);\n        writeUndefined(buf);\n    }\n\n    function writeKVMap(CBORBuffer memory buf, string memory key) internal pure {\n        writeString(buf, key);\n        startMap(buf);\n    }\n\n    function writeKVArray(CBORBuffer memory buf, string memory key) internal pure {\n        writeString(buf, key);\n        startArray(buf);\n    }\n\n    function writeFixedNumeric(\n        CBORBuffer memory buf,\n        uint8 major,\n        uint64 value\n    ) private pure {\n        if (value <= 23) {\n            buf.buf.appendUint8(uint8((major << 5) | value));\n        } else if (value <= 0xFF) {\n            buf.buf.appendUint8(uint8((major << 5) | 24));\n            buf.buf.appendInt(value, 1);\n        } else if (value <= 0xFFFF) {\n            buf.buf.appendUint8(uint8((major << 5) | 25));\n            buf.buf.appendInt(value, 2);\n        } else if (value <= 0xFFFFFFFF) {\n            buf.buf.appendUint8(uint8((major << 5) | 26));\n            buf.buf.appendInt(value, 4);\n        } else {\n            buf.buf.appendUint8(uint8((major << 5) | 27));\n            buf.buf.appendInt(value, 8);\n        }\n    }\n\n    function writeIndefiniteLengthType(CBORBuffer memory buf, uint8 major)\n        private\n        pure\n    {\n        buf.buf.appendUint8(uint8((major << 5) | 31));\n    }\n\n    function writeDefiniteLengthType(CBORBuffer memory buf, uint8 major, uint64 length)\n        private\n        pure\n    {\n        writeFixedNumeric(buf, major, length);\n    }\n\n    function writeContentFree(CBORBuffer memory buf, uint8 value) private pure {\n        buf.buf.appendUint8(uint8((MAJOR_TYPE_CONTENT_FREE << 5) | value));\n    }\n}"},{"file_path":"@openzeppelin/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"./IAccessControl.sol\";\nimport {Context} from \"../utils/Context.sol\";\nimport {ERC165} from \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 role => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        return _roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (!hasRole(role, account)) {\n            _roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (hasRole(role, account)) {\n            _roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"},{"file_path":"@openzeppelin/contracts/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":"@openzeppelin/contracts/utils/Pausable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.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 Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\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":"@openzeppelin/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":"@openzeppelin/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"nav-oracle-public/contracts/interfaces/INAVConsumer.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {INAVReceiver} from \"./INAVReceiver.sol\";\n\n// Authentication and Access Control Errors\nerror UnauthorizedNAVUpdateRequest();\n\n// Configuration Errors\nerror InvalidSubscriptionId();\nerror InvalidDonId();\nerror InvalidSourceCode();\nerror InvalidGasLimit(uint32 minimum);\nerror InvalidEncryptedSecretsReference();\n\n// Validation Errors\nerror DeviationCannotBeZero();\nerror InvalidNAVValue(uint256 navValue);\n\n// Automation Errors\nerror UpkeepConditionsNotMet();\n\n// Time Parameter Errors\nerror InvalidTargetHour();\nerror InvalidTargetMinute();\nerror InvalidTimeWindow();\n\n// Force Update Errors\nerror ForceUpdateTooFrequent(uint256 timeSinceLastUpdate, uint256 minimumRequired);\n\n// Receiver Errors\nerror InvalidReceiverAddress();\n\n// Constructor Errors\nerror ZeroAddress(string parameter);\n\n// Unexpected Request ID Error\nerror UnexpectedRequestID(bytes32 requestId);\n\n/**\n * @title NAV Consumer Interface\n * @notice Interface for the NAV Consumer contract with Chainlink Functions and Automation\n * @dev This interface declares all external functions, events, and errors for the NAV Consumer contract\n *      - Provides automated Net Asset Value (NAV) updates via Chainlink Functions and Automation\n *      - Supports manual and emergency NAV update mechanisms\n *      - Includes deviation checks to prevent erroneous NAV updates\n *      - Integrates with NAV receivers to propagate NAV updates to dependent contracts\n *      - Uses role-based access control for secure operation\n */\ninterface INAVConsumer {\n    // Events\n    /**\n     * @notice Emitted when the NAV value is updated (applies to all types of updates)\n     * @param timestamp The block timestamp when the NAV was updated\n     * @param navValue The new NAV value\n     */\n    event NAVUpdated(uint256 indexed timestamp, uint256 navValue);\n    \n    /**\n     * @notice Emitted when a NAV request is sent to Chainlink Functions\n     * @param requestId The unique ID for the Chainlink Functions request\n     */\n    event NAVRequestSent(bytes32 indexed requestId);\n    \n    /**\n     * @notice Emitted when a NAV request is successfully fulfilled by Chainlink Functions\n     * @param requestId The unique ID for the Chainlink Functions request\n     * @param navValue The NAV value received from the oracle\n     */\n    event NAVFulfilled(bytes32 indexed requestId, uint256 navValue);\n    \n    /**\n     * @notice Emitted when a NAV request fails\n     * @param requestId The unique ID for the Chainlink Functions request\n     * @param error The error message explaining the failure\n     */\n    event NAVRequestFailed(bytes32 indexed requestId, string error);\n    \n    /**\n     * @notice Emitted when an automated update is triggered via Chainlink Automation\n     * @param timestamp The block timestamp when the automated update was triggered\n     */\n    event AutomatedUpdateTriggered(uint256 timestamp);\n    \n    /**\n     * @notice Emitted when a NAV update is rejected due to excessive deviation\n     * @param requestId The unique ID for the Chainlink Functions request\n     * @param newNav The new NAV value that was rejected\n     * @param previousNav The previous NAV value used for comparison\n     * @param deviationBps The calculated deviation in basis points\n     */\n    event ExcessiveNAVDeviation(bytes32 indexed requestId, uint256 newNav, uint256 previousNav, uint256 deviationBps);\n    \n    /**\n     * @notice Emitted when the maximum allowed deviation is updated\n     * @param newMaxDeviationBps The new maximum deviation threshold in basis points\n     */\n    event MaxDeviationUpdated(uint256 newMaxDeviationBps);\n    \n    /**\n     * @notice Emitted when the deviation check is enabled or disabled\n     * @param enabled The new state of the deviation check\n     */\n    event DeviationCheckToggled(bool enabled);\n    \n    /**\n     * @notice Emitted when a NAV value is force updated by an emergency updater\n     * @param timestamp The block timestamp when the force update occurred\n     * @param navValue The new NAV value set via force update\n     * @param deviationBps The calculated deviation in basis points\n     * @param reason The reason provided for the force update\n     * @param caller The address that performed the force update\n     */\n    event NAVForceUpdated(uint256 indexed timestamp, uint256 navValue, uint256 deviationBps, string reason, address caller);\n    \n    /**\n     * @notice Emitted when a new NAV receiver is set\n     * @param receiver The address of the new NAV receiver\n     */\n    event NAVReceiverUpdated(address indexed receiver);\n    \n    /**\n     * @notice Emitted when an update to a NAV receiver fails\n     * @param navValue The NAV value that failed to be set\n     * @param receiver The address of the NAV receiver that failed\n     */\n    event NAVReceiverUpdateFailed(uint256 navValue, address receiver);\n    \n    /**\n     * @notice Emitted when automation time parameters are updated\n     * @param targetHour The new target hour for daily updates\n     * @param targetMinute The new target minute for daily updates\n     * @param timeWindow The new time window in seconds\n     */\n    event AutomationParametersUpdated(uint256 targetHour, uint256 targetMinute, uint256 timeWindow);\n    \n    /**\n     * @notice Emitted when the contract is paused due to excessive deviation\n     * @param requestId The unique ID for the Chainlink Functions request\n     * @param newNav The new NAV value that caused the deviation\n     * @param previousNav The previous NAV value used for comparison\n     * @param deviationBps The calculated deviation in basis points\n     */\n    event PausedDueToDeviation(bytes32 indexed requestId, uint256 newNav, uint256 previousNav, uint256 deviationBps);\n\n    /**\n     * @notice Emitted when automation is enabled or disabled\n     * @param enabled The new state of automation (true=enabled, false=disabled)\n     * @param caller The address that changed the setting\n     */\n    event AutomationEnabledChanged(bool enabled, address indexed caller);\n    \n    /**\n     * @notice Emitted when the callback gas limit is updated\n     * @param oldLimit The previous gas limit value\n     * @param newLimit The new gas limit value\n     * @param caller The address that changed the setting\n     */\n    event CallbackGasLimitUpdated(uint32 oldLimit, uint32 newLimit, address indexed caller);\n    \n    /**\n     * @notice Emitted when Chainlink Functions configuration is updated\n     * @param subscriptionId The new Chainlink Functions subscription ID\n     * @param donId The new Decentralized Oracle Network ID\n     * @param sourceCodeHash Hash of the source code for identification\n     * @param secretsReferenceHash Hash of the encrypted secrets reference for identification\n     * @param caller The address that changed the configuration\n     */\n    event ConfigurationUpdated(uint64 subscriptionId, bytes32 donId, bytes32 sourceCodeHash, bytes32 secretsReferenceHash, address indexed caller);\n\n    \n    // External functions\n    \n    /**\n     * @notice Enable or disable the automation feature\n     * @param enabled True to enable, false to disable\n     * @dev Only callable by admin role\n     */\n    function setAutomationEnabled(bool enabled) external;\n    \n    /**\n     * @notice Configure the Chainlink Functions parameters\n     * @param _subscriptionId The Chainlink Functions subscription ID for billing\n     * @param _donId The Decentralized Oracle Network ID\n     * @param _source The JavaScript source code to be executed by Chainlink Functions\n     * @param _encryptedSecretsReference Reference to encrypted secrets for the source code\n     * @dev Only callable by admin role\n     */\n    function configure(\n        uint64 _subscriptionId,\n        bytes32 _donId,\n        string calldata _source,\n        bytes calldata _encryptedSecretsReference\n    ) external;\n    \n    /**\n     * @notice Set the gas limit for the Chainlink Functions callback\n     * @param _callbackGasLimit Gas limit for the fulfillRequest callback function\n     * @dev Only callable by admin role\n     */\n    function setCallbackGasLimit(uint32 _callbackGasLimit) external;\n    \n    /**\n     * @notice Request a NAV update from Chainlink Functions\n     * @return requestId The unique ID for this request\n     * @dev Only callable by admin or updater roles\n     */\n    function requestNAV() external returns (bytes32 requestId);\n    \n    /**\n     * @notice Entry point for Chainlink Automation to trigger NAV updates\n     * @param performData Arbitrary data passed from checkUpkeep to performUpkeep\n     * @dev Only callable by the Chainlink Automation registry\n     */\n    function performUpkeep(bytes calldata performData) external;\n    \n    /**\n     * @notice Set the maximum allowed deviation for NAV updates in basis points\n     * @param _maxDeviationBps The maximum allowed deviation (e.g., 1000 = 10%)\n     * @dev Only callable by admin role, cannot be set to zero\n     */\n    function setMaxDeviation(uint256 _maxDeviationBps) external;\n    \n    /**\n     * @notice Enable or disable the deviation check feature\n     * @param _enabled True to enable, false to disable deviation checks\n     * @dev Only callable by admin role\n     */\n    function setDeviationCheckEnabled(bool _enabled) external;\n    \n    /**\n     * @notice Force update the NAV value, bypassing the Chainlink Functions request\n     * @param _navValue The NAV value to set\n     * @param _reason Description explaining why this force update is necessary\n     * @dev Only callable by emergency updater role, subject to time restrictions\n     */\n    function forceNAVUpdate(uint256 _navValue, string calldata _reason) external;\n    \n    /**\n     * @notice Set the address of the NAV receiver contract\n     * @param _navReceiver The address of the contract implementing INAVReceiver\n     * @dev Only callable by admin role, cannot be zero address\n     */\n    function setNAVReceiver(address _navReceiver) external;\n    \n    /**\n     * @notice Get the current NAV value and its timestamp\n     * @return nav The latest NAV value with 18 decimal places\n     * @return timestamp The timestamp when this NAV value was last updated\n     */\n    function getCurrentNAV() external view returns (uint256 nav, uint256 timestamp);\n    \n    /**\n     * @notice Get the previous NAV value and its timestamp\n     * @return nav The previous NAV value with 18 decimal places\n     * @return timestamp The timestamp when the previous NAV value was updated\n     */\n    function getPreviousNAV() external view returns (uint256 nav, uint256 timestamp);\n    \n    /**\n     * @notice Calculate the percentage change between latest and previous NAV\n     * @return percentageChange The percentage change with 8 decimal places (e.g., 100000000 = 1%)\n     * @dev Returns 0 if there is no previous NAV\n     */\n    function getPercentageChange() external view returns (int256 percentageChange);\n\n    // Read-only state variables\n    \n    /**\n     * @notice Get the latest Chainlink Functions request ID\n     * @return The bytes32 request ID of the most recent request\n     */\n    function latestRequestId() external view returns (bytes32);\n    \n    /**\n     * @notice Get the timestamp of the latest NAV update\n     * @return The block timestamp when the latest NAV was updated\n     */\n    function latestTimestamp() external view returns (uint256);\n    \n    /**\n     * @notice Get the timestamp of the previous NAV update\n     * @return The block timestamp when the previous NAV was updated\n     */\n    function previousTimestamp() external view returns (uint256);\n    \n    /**\n     * @notice Get the Chainlink Functions DON ID used for requests\n     * @return The bytes32 DON ID\n     */\n    function donId() external view returns (bytes32);\n    \n    /**\n     * @notice Get the Chainlink Functions subscription ID used for billing\n     * @return The subscription ID\n     */\n    function subscriptionId() external view returns (uint64);\n    \n    /**\n     * @notice Get the timestamp of the last automated update via Chainlink Automation\n     * @return The block timestamp of the last automated update\n     */\n    function lastAutomatedUpdateTimestamp() external view returns (uint256);\n    \n    /**\n     * @notice Get the timestamp of the last force update\n     * @return The block timestamp of the last force update\n     */\n    function lastForceUpdateTimestamp() external view returns (uint256);\n    \n    /**\n     * @notice Check if automation is currently enabled\n     * @return True if automation is enabled, false otherwise\n     */\n    function automationEnabled() external view returns (bool);\n    \n    /**\n     * @notice Get the maximum allowed deviation in basis points\n     * @return The maximum deviation threshold in basis points (e.g., 1000 = 10%)\n     */\n    function maxDeviationBps() external view returns (uint256);\n    \n    /**\n     * @notice Check if deviation check is currently enabled\n     * @return True if deviation check is enabled, false otherwise\n     */\n    function deviationCheckEnabled() external view returns (bool);\n    \n    /**\n     * @notice Get the current NAV receiver contract\n     * @return The address of the contract implementing INAVReceiver\n     */\n    function navReceiver() external view returns (INAVReceiver);\n    \n    /**\n     * @notice Get the number of decimal places used in NAV values\n     * @return The number of decimal places (18)\n     * @dev NAV values are fixed-point numbers with 18 decimal places\n     */\n    function decimals() external pure returns (uint8);\n}"},{"file_path":"nav-oracle-public/contracts/interfaces/INAVReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\n/**\n * @title NAV Receiver Interface\n * @notice Interface for contracts that receive and process NAV updates from NAVConsumer\n * @dev Any contract that needs to receive and act on NAV updates should implement this interface\n */\ninterface INAVReceiver {\n    /**\n     * @notice Updates the share price based on the provided NAV value\n     * @param nav The NAV value with 18 decimal places\n     * @dev This function is called by the NAVConsumer contract when the NAV is updated\n     *      Implementations should handle potential failure gracefully as the NAVConsumer\n     *      will not revert if this function fails\n     */\n    function setSharePrice(uint256 nav) external;\n}\n"},{"file_path":"nav-oracle-public/contracts/test/ChainedNAVReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {INAVReceiver} from \"../interfaces/INAVReceiver.sol\";\n\n/**\n * @title Chained NAV Receiver\n * @notice A contract that implements INAVReceiver and forwards updates to another receiver\n * @dev Used for testing multi-receiver scenarios\n */\ncontract ChainedNAVReceiver is INAVReceiver {\n    // The current share price\n    uint256 public sharePrice;\n    \n    // The next receiver in the chain\n    INAVReceiver public nextReceiver;\n    \n    // Track update propagation\n    uint256 public updateCount;\n    uint256 public lastUpdatedValue;\n    bool public propagateUpdates = true;\n    bool public shouldFail = false;\n    \n    // Event for tracking updates\n    event SharePriceUpdated(uint256 oldPrice, uint256 newPrice);\n    event UpdatePropagated(address nextReceiver, uint256 value);\n    \n    /**\n     * @notice Constructor to initialize with an optional next receiver\n     * @param _nextReceiver The next receiver in the chain\n     */\n    constructor(address _nextReceiver) {\n        if (_nextReceiver != address(0)) {\n            nextReceiver = INAVReceiver(_nextReceiver);\n        }\n    }\n    \n    /**\n     * @notice Set the next receiver in the chain\n     * @param _nextReceiver The address of the next receiver\n     */\n    function setNextReceiver(address _nextReceiver) external {\n        nextReceiver = INAVReceiver(_nextReceiver);\n    }\n    \n    /**\n     * @notice Control whether to propagate updates to the next receiver\n     * @param _propagate Whether to propagate updates\n     */\n    function setPropagateUpdates(bool _propagate) external {\n        propagateUpdates = _propagate;\n    }\n    \n    /**\n     * @notice Toggle failure mode (for testing error handling)\n     * @param _shouldFail Whether this receiver should fail when updated\n     */\n    function setShouldFail(bool _shouldFail) external {\n        shouldFail = _shouldFail;\n    }\n    \n    /**\n     * @notice Implementation of setSharePrice from INAVReceiver\n     * @param nav The new NAV value\n     */\n    function setSharePrice(uint256 nav) external override {\n        if (shouldFail) {\n            revert(\"ChainedNAVReceiver: Intentional failure\");\n        }\n        \n        // Store the old price for the event\n        uint256 oldPrice = sharePrice;\n        \n        // Update the share price\n        sharePrice = nav;\n        lastUpdatedValue = nav;\n        updateCount++;\n        \n        // Emit event\n        emit SharePriceUpdated(oldPrice, nav);\n        \n        // Propagate to the next receiver if configured\n        if (address(nextReceiver) != address(0) && propagateUpdates) {\n            try nextReceiver.setSharePrice(nav) {\n                emit UpdatePropagated(address(nextReceiver), nav);\n            } catch {\n                // Silently catch errors from next receiver\n                // This ensures errors don't bubble up to the NAVConsumer\n            }\n        }\n    }\n    \n    /**\n     * @notice Get the current share price\n     * @return The current share price\n     */\n    function getSharePrice() external view returns (uint256) {\n        return sharePrice;\n    }\n    \n    /**\n     * @notice Reset the update counter (for testing)\n     */\n    function resetUpdateCount() external {\n        updateCount = 0;\n    }\n}"},{"file_path":"nav-oracle-public/contracts/test/FailingMockNAVReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {INAVReceiver} from \"../interfaces/INAVReceiver.sol\";\n\n/**\n * @title Failing NAV Receiver Mock\n * @notice This mock receiver always reverts when setSharePrice is called\n * @dev Used for testing error handling in the NAV Consumer\n */\ncontract FailingMockNAVReceiver is INAVReceiver {\n    // Custom error for explaining failures\n    error AlwaysFailingReceiver();\n    \n    // This will never be updated since all calls revert\n    uint256 public sharePrice;\n    \n    /**\n     * @notice Implementation of setSharePrice that always reverts\n     * @dev Unused parameter intentionally unnamed to avoid compiler warnings\n     */\n    function setSharePrice(uint256) external pure override {\n        revert AlwaysFailingReceiver();\n    }\n}"},{"file_path":"nav-oracle-public/contracts/test/MaliciousNAVReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {INAVReceiver} from \"../interfaces/INAVReceiver.sol\";\nimport {INAVConsumer} from \"../interfaces/INAVConsumer.sol\";\n\n/**\n * @title Malicious NAV Receiver\n * @notice This contract attempts to perform reentrancy attacks on the NAV Consumer\n * @dev Used only for testing reentrancy protections\n */\ncontract MaliciousNAVReceiver is INAVReceiver {\n    // The NAV consumer contract that will be targeted\n    address public navConsumer;\n    \n    // The target function for reentrancy\n    string public reentrancyTarget;\n    \n    // Share price state\n    uint256 public sharePrice;\n    \n    // Custom attack parameters\n    uint256 public attackNav = 9999999; // Default attack NAV value\n    address public attackReceiver; // Address to try to set as a new receiver\n    address public nextReceiver; // Next receiver in a chain attack\n    \n    // Tracking variables\n    bool public reentrancyAttempted;\n    uint256 public callCounter;\n    \n    /**\n     * @notice Constructor\n     */\n    constructor() {\n        // Default initialization - navConsumer will be set later\n    }\n    \n    /**\n     * @notice Set the NAV consumer contract address\n     * @param _navConsumer The address of the NAV consumer contract\n     */\n    function setNAVConsumer(address _navConsumer) external {\n        navConsumer = _navConsumer;\n    }\n    \n    /**\n     * @notice Set the target function for reentrancy\n     * @param _target The function to target ('forceNAVUpdate', 'requestNAV', or 'setNAVReceiver')\n     */\n    function setReentrancyTarget(string calldata _target) external {\n        reentrancyTarget = _target;\n    }\n    \n    /**\n     * @notice Set the NAV value to use in attacks\n     * @param _attackNav The NAV value to try to set during reentrancy\n     */\n    function setAttackNav(uint256 _attackNav) external {\n        attackNav = _attackNav;\n    }\n    \n    /**\n     * @notice Set the receiver address to use in setNAVReceiver attacks\n     * @param _attackReceiver The address to try to set as a new receiver\n     */\n    function setAttackReceiver(address _attackReceiver) external {\n        attackReceiver = _attackReceiver;\n    }\n    \n    /**\n     * @notice Set the next receiver for chained attacks\n     * @param _nextReceiver The address of the next malicious receiver\n     */\n    function setNextReceiver(address _nextReceiver) external {\n        nextReceiver = _nextReceiver;\n    }\n    \n    /**\n     * @notice Implementation of setSharePrice that attempts reentrancy\n     * @param _sharePrice The new share price\n     */\n    function setSharePrice(uint256 _sharePrice) external override {\n        // Store the share price\n        sharePrice = _sharePrice;\n        \n        // Increment call counter for test verification\n        callCounter++;\n        \n        // Mark that we attempted reentrancy\n        reentrancyAttempted = true;\n        \n        // Attempt the appropriate attack based on target string\n        if (keccak256(abi.encodePacked(reentrancyTarget)) == keccak256(abi.encodePacked(\"forceNAVUpdate\"))) {\n            // Try to reenter forceNAVUpdate with the new signature\n            try INAVConsumer(navConsumer).forceNAVUpdate(attackNav, \"Malicious update\") {\n                // If successful, this would be unexpected in a secure contract\n            } catch {\n                // Expected to fail due to reentrancy guard\n            }\n        } else if (keccak256(abi.encodePacked(reentrancyTarget)) == keccak256(abi.encodePacked(\"requestNAV\"))) {\n            // Try to reenter requestNAV\n            try INAVConsumer(navConsumer).requestNAV() {\n                // If successful, this would be unexpected in a secure contract\n            } catch {\n                // Expected to fail due to reentrancy guard or role check\n            }\n        } else if (keccak256(abi.encodePacked(reentrancyTarget)) == keccak256(abi.encodePacked(\"setNAVReceiver\"))) {\n            // Try to reenter setNAVReceiver \n            try INAVConsumer(navConsumer).setNAVReceiver(attackReceiver) {\n                // If successful, this would be unexpected in a secure contract\n            } catch {\n                // Expected to fail due to reentrancy guard or role check\n            }\n        }\n        \n        // If we have a next receiver, try to change to it (multi-step attack)\n        if (nextReceiver != address(0)) {\n            try INAVConsumer(navConsumer).setNAVReceiver(nextReceiver) {\n                // If successful, this would be unexpected in a secure contract\n            } catch {\n                // Expected to fail due to reentrancy guard or role check\n            }\n        }\n    }\n    \n    /**\n     * @notice Get the current share price\n     * @return The current share price\n     */\n    function getSharePrice() external view returns (uint256) {\n        return sharePrice;\n    }\n} "},{"file_path":"nav-oracle-public/contracts/test/MockFunctionsRouter.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {IFunctionsClient} from \"@chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol\";\n\n/**\n * @title Mock Functions Router\n * @notice Mock implementation of Chainlink Functions Router for testing\n */\ncontract MockFunctionsRouter {\n    event RequestProcessed(bytes32 indexed requestId, address consumer);\n    event ResponseDelivered(bytes32 indexed requestId, address consumer, bytes response, bytes error);\n\n    /**\n     * @notice Process a request directly (for testing)\n     * @param consumer The consumer contract address\n     * @param requestId The request ID to process\n     * @param response The response data to send\n     * @param err Any error message\n     */\n    function sendResponse(\n        address consumer,\n        bytes32 requestId,\n        bytes memory response,\n        bytes memory err\n    ) external {\n        // Call the consumer's handleOracleFulfillment function (matches IFunctionsClient interface)\n        IFunctionsClient(consumer).handleOracleFulfillment(requestId, response, err);\n        \n        emit ResponseDelivered(requestId, consumer, response, err);\n    }\n    \n    /**\n     * @notice Alternative name for sendResponse (for compatibility with different test styles)\n     */\n    function fulfillRequest(\n        address consumer,\n        bytes32 requestId,\n        bytes memory response,\n        bytes memory err\n    ) external {\n        // Call the consumer's handleOracleFulfillment function (matches IFunctionsClient interface)\n        IFunctionsClient(consumer).handleOracleFulfillment(requestId, response, err);\n        \n        emit ResponseDelivered(requestId, consumer, response, err);\n    }\n\n    /**\n     * @notice Mock implementation of sendRequest from IFunctionsRouter\n     * @dev This function returns a deterministic requestId for testing\n     */\n    function sendRequest(\n        uint64 subscriptionId,\n        bytes calldata data,\n        uint16 dataVersion,\n        uint32 callbackGasLimit,\n        bytes32 donId\n    ) external returns (bytes32) {\n        // Create a deterministic requestId based on inputs for testing predictability\n        bytes32 requestId = keccak256(\n            abi.encode(\n                msg.sender,\n                subscriptionId,\n                data,\n                dataVersion,\n                callbackGasLimit,\n                donId,\n                block.timestamp\n            )\n        );\n        \n        // Store the request info\n        latestRequestId = requestId;\n        requestCount++;\n        \n        emit RequestProcessed(requestId, msg.sender);\n        return requestId;\n    }\n    \n    // For testing - track request info\n    bytes32 public latestRequestId;\n    uint256 public requestCount;\n    \n    /**\n     * @notice Get the latest request ID\n     */\n    function getLatestRequestId() external view returns (bytes32) {\n        return latestRequestId;\n    }\n    \n    /**\n     * @notice Get the count of requests\n     */\n    function getRequestCount() external view returns (uint256) {\n        return requestCount;\n    }\n    \n    /**\n     * @notice Simplified version of sendResponse - renamed to avoid overloading issues\n     * @param requestId The request ID to process\n     * @param response The response data to send\n     * @param err Any error message\n     */\n    function sendSimpleResponse(\n        bytes32 requestId,\n        bytes memory response,\n        bytes memory err\n    ) external {\n        // Call the consumer's handleOracleFulfillment function (matches IFunctionsClient interface)\n        IFunctionsClient(msg.sender).handleOracleFulfillment(requestId, response, err);\n        \n        emit ResponseDelivered(requestId, msg.sender, response, err);\n    }\n}"},{"file_path":"nav-oracle-public/contracts/test/MockNAVReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.29;\n\nimport {INAVReceiver} from \"../interfaces/INAVReceiver.sol\";\n\ncontract MockNAVReceiver is INAVReceiver {\n    uint256 public sharePrice;\n    bool public shouldRevert;\n    \n    event SharePriceUpdated(uint256 value);\n    \n    function setSharePrice(uint256 nav) external override {\n        require(!shouldRevert, \"MockNAVReceiver: reverting as configured\");\n        sharePrice = nav;\n        emit SharePriceUpdated(nav);\n    }\n    \n    function setShouldRevert(bool _shouldRevert) external {\n        shouldRevert = _shouldRevert;\n    }\n} "}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"updater","type":"address"},{"internalType":"address","name":"emergencyUpdater","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"DeviationCannotBeZero","type":"error"},{"inputs":[],"name":"EmptySecrets","type":"error"},{"inputs":[],"name":"EmptySource","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"uint256","name":"timeSinceLastUpdate","type":"uint256"},{"internalType":"uint256","name":"minimumRequired","type":"uint256"}],"name":"ForceUpdateTooFrequent","type":"error"},{"inputs":[],"name":"InvalidDonId","type":"error"},{"inputs":[],"name":"InvalidEncryptedSecretsReference","type":"error"},{"inputs":[{"internalType":"uint32","name":"minimum","type":"uint32"}],"name":"InvalidGasLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"navValue","type":"uint256"}],"name":"InvalidNAVValue","type":"error"},{"inputs":[],"name":"InvalidReceiverAddress","type":"error"},{"inputs":[],"name":"InvalidSourceCode","type":"error"},{"inputs":[],"name":"InvalidSubscriptionId","type":"error"},{"inputs":[],"name":"InvalidTargetHour","type":"error"},{"inputs":[],"name":"InvalidTargetMinute","type":"error"},{"inputs":[],"name":"InvalidTimeWindow","type":"error"},{"inputs":[],"name":"NoInlineSecrets","type":"error"},{"inputs":[],"name":"OnlyRouterCanFulfill","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"UnauthorizedNAVUpdateRequest","type":"error"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"UnexpectedRequestID","type":"error"},{"inputs":[],"name":"UpkeepConditionsNotMet","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"}],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AutomatedUpdateTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"AutomationEnabledChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetHour","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetMinute","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeWindow","type":"uint256"}],"name":"AutomationParametersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"oldLimit","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newLimit","type":"uint32"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"CallbackGasLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"subscriptionId","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"donId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"sourceCodeHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"secretsReferenceHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"ConfigurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"DeviationCheckToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newNav","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousNav","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deviationBps","type":"uint256"}],"name":"ExcessiveNAVDeviation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxDeviationBps","type":"uint256"}],"name":"MaxDeviationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deviationBps","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"NAVForceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"navValue","type":"uint256"}],"name":"NAVFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"navValue","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"}],"name":"NAVReceiverUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"NAVReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"error","type":"string"}],"name":"NAVRequestFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"NAVRequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navValue","type":"uint256"}],"name":"NAVUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newNav","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousNav","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deviationBps","type":"uint256"}],"name":"PausedDueToDeviation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"RequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_UPDATER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_CALLBACK_GAS_LIMIT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FORCE_UPDATE_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPDATER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"automationEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"bytes32","name":"_donId","type":"bytes32"},{"internalType":"string","name":"_source","type":"string"},{"internalType":"bytes","name":"_encryptedSecretsReference","type":"bytes"}],"name":"configure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"deviationCheckEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_navValue","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"forceNAVUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentNAV","outputs":[{"internalType":"uint256","name":"nav","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPercentageChange","outputs":[{"internalType":"int256","name":"percentageChange","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPreviousNAV","outputs":[{"internalType":"uint256","name":"nav","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"bytes","name":"response","type":"bytes"},{"internalType":"bytes","name":"err","type":"bytes"}],"name":"handleOracleFulfillment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastAutomatedUpdateTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastForceUpdateTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRequestId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDeviationBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"navReceiver","outputs":[{"internalType":"contract INAVReceiver","name":"","type":"address"}],"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":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"previousTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestNAV","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setAutomationEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetHour","type":"uint256"},{"internalType":"uint256","name":"_targetMinute","type":"uint256"},{"internalType":"uint256","name":"_timeWindow","type":"uint256"}],"name":"setAutomationTimeParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"setCallbackGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setDeviationCheckEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDeviationBps","type":"uint256"}],"name":"setMaxDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_navReceiver","type":"address"}],"name":"setNAVReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetHour","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetMinute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeWindow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x00000000000000000000000065dcc24f8ff9e51f10dcc7ed1e4e2a61e6e14bd60000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe576490000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe576490000000000000000000000006c15b25e9750dccb698c1a4023f34015bfe57649"}