Market: DoS when stuffed with pending protected positions
In `_invariant`, there is a limit on the number of pending position updates. But for `protected` position updates, `_invariant` returns early and does not trigger this check.\\n```\\n    function _invariant(\\n        Context memory context,\\n        address account,\\n        Order memory newOrder,\\n        Fixed6 collateral,\\n        bool protected\\n    ) private view {\\n        // rest of code.\\n\\n        if (protected) return; // The following invariants do not apply to protected position updates (liquidations)\\n        // rest of code.\\n            if (\\n            context.global.currentId > context.global.latestId + context.marketParameter.maxPendingGlobal ||\\n            context.local.currentId > context.local.latestId + context.marketParameter.maxPendingLocal\\n        ) revert MarketExceedsPendingIdLimitError();\\n        // rest of code.\\n    }\\n```\\n\\nAfter the `_invariant` check, the postion updates will be added into pending position queues.\\n```\\n        _invariant(context, account, newOrder, collateral, protected);\\n\\n        // store\\n        _pendingPosition[context.global.currentId].store(context.currentPosition.global);\\n        _pendingPositions[account][context.local.currentId].store(context.currentPosition.local);\\n```\\n\\nWhen the protocol enters next oracle version, the global pending queue `_pendingPosition` will be settled in a loop.\\n```\\n    function _settle(Context memory context, address account) private {\\n        // rest of code.\\n        // settle\\n        while (\\n            context.global.currentId != context.global.latestId &&\\n            (nextPosition = _pendingPosition[context.global.latestId + 1].read()).ready(context.latestVersion)\\n        ) _processPositionGlobal(context, context.global.latestId + 1, nextPosition);\\n```\\n\\nThe OOG revert happens if there are too many pending position updates.\\nThis revert will happend on every `update` calls because they all need to settle this `_pendingPosition` before `update`.\\n```\\n    function update(\\n        address account,\\n        UFixed6 newMaker,\\n        UFixed6 newLong,\\n        UFixed6 newShort,\\n        Fixed6 collateral,\\n        bool protect\\n    ) external nonReentrant whenNotPaused {\\n        Context memory context = _loadContext(account);\\n        _settle(context, account);\\n        _update(context, account, newMaker, newLong, newShort, collateral, protect);\\n        _saveContext(context, account);\\n    }\\n```\\n
Either or both,\\nLimit the number of pending protected position updates can be queued in `_invariant`.\\nLimit the number of global pending protected postions can be settled in `_settle`.
The protocol will be fully unfunctional and funds will be locked. There will be no recover to this DoS.\\nA malicious user can tigger this intentionally at very low cost. Alternatively, this can occur during a volatile market period when there are massive liquidations.
```\\n    function _invariant(\\n        Context memory context,\\n        address account,\\n        Order memory newOrder,\\n        Fixed6 collateral,\\n        bool protected\\n    ) private view {\\n        // rest of code.\\n\\n        if (protected) return; // The following invariants do not apply to protected position updates (liquidations)\\n        // rest of code.\\n            if (\\n            context.global.currentId > context.global.latestId + context.marketParameter.maxPendingGlobal ||\\n            context.local.currentId > context.local.latestId + context.marketParameter.maxPendingLocal\\n        ) revert MarketExceedsPendingIdLimitError();\\n        // rest of code.\\n    }\\n```\\n