{
    "Function": "canWithdraw",
    "File": "src/contracts/core/Slasher.sol",
    "Parent Contracts": [
        "src/contracts/permissions/Pausable.sol",
        "src/contracts/interfaces/IPausable.sol",
        "src/contracts/interfaces/ISlasher.sol",
        "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol",
        "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol",
        "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"
    ],
    "High-Level Calls": [],
    "Internal Calls": [],
    "Library Calls": [],
    "Low-Level Calls": [],
    "Code": "function canWithdraw(address operator, uint32 withdrawalStartBlock, uint256 middlewareTimesIndex) external view returns (bool) {\n        // if the operator has never registered for a middleware, just return 'true'\n        if (_operatorToMiddlewareTimes[operator].length == 0) {\n            return true;\n        }\n\n        // pull the MiddlewareTimes struct at the `middlewareTimesIndex`th position in `_operatorToMiddlewareTimes[operator]`\n        MiddlewareTimes memory update = _operatorToMiddlewareTimes[operator][middlewareTimesIndex];\n\n        /**\n         * Case-handling for if the operator is not registered for any middlewares (i.e. they previously registered but are no longer registered for any),\n         * AND the withdrawal was initiated after the 'stalestUpdateBlock' of the MiddlewareTimes struct specified by the provided `middlewareTimesIndex`.\n         * NOTE: we check the 2nd of these 2 conditions first for gas efficiency, to help avoid an extra SLOAD in all other cases.\n         */\n        if (withdrawalStartBlock >= update.stalestUpdateBlock && _operatorToWhitelistedContractsByUpdate[operator].size == 0) {\n            /**\n             * In this case, we just check against the 'latestServeUntilBlock' of the last MiddlewareTimes struct. This is because the operator not being registered\n             * for any middlewares (i.e. `_operatorToWhitelistedContractsByUpdate.size == 0`) means no new MiddlewareTimes structs will be being pushed, *and* the operator \n             * will not be undertaking any new obligations (so just checking against the last entry is OK, unlike when the operator is actively registered for >=1 middleware).\n             */\n            update = _operatorToMiddlewareTimes[operator][_operatorToMiddlewareTimes[operator].length - 1];\n            return (uint32(block.number) > update.latestServeUntilBlock);\n        }\n        \n        /**\n         * Make sure the stalest update block at the time of the update is strictly after `withdrawalStartBlock` and ensure that the current time\n         * is after the `latestServeUntilBlock` of the update. This assures us that this that all middlewares were updated after the withdrawal began, and\n         * that the stake is no longer slashable.\n         */\n        return(\n            withdrawalStartBlock < update.stalestUpdateBlock \n            &&\n            uint32(block.number) > update.latestServeUntilBlock\n        );\n    }"
}