Underflow Vulnerability in `Market::_allowedBorrow` Function: Oversight with Pearlmit Allowance Handling
The protocol permits users to authorize spenders using the MarketERC20::approveBorrow function, and also includes support for allowances granted through the `Pearlmit` contract. However, an oversight in the _allowedBorrow function leads to an underflow issue when spenders utilize `Pearlmit` allowances, rendering them unable to execute borrowing actions despite having the necessary permission.\\nProtocol users can approve a spender via MarketERC20::approveBorrow function, to perform certain actions like `borrow`, `repay` or adding of collateral on their behalf. Whenever the spender calls any of these functionalities, down the execution _allowedBorrow is invoked to check if the caller is allowed to `borrow` `share` `from` `from`, and then decrease the spender's allowance by the `share` amount.\\n```\\n    function _allowedBorrow(address from, uint256 share) internal virtual override {\\n        if (from != msg.sender) {\\n            // TODO review risk of using this\\n            (uint256 pearlmitAllowed,) = penrose.pearlmit().allowance(from, msg.sender, address(yieldBox), collateralId);\\n            require(allowanceBorrow[from][msg.sender] >= share || pearlmitAllowed >= share, "Market: not approved");\\n            if (allowanceBorrow[from][msg.sender] != type(uint256).max) {\\n                allowanceBorrow[from][msg.sender] -= share;\\n            }\\n        }\\n    }\\n```\\n\\nThe problem here is, _allowedBorrow will always revert due to an underflow whenever the spender is given an allowance in the `Pearlmit` contract.\\nTo Illustrate\\nAssuming we have two users, Bob and Alice, since `Pearlmit` allowance is also accepted, Alice grants Bob a borrowing allowance of `100` tokens for the collateral id using `Pearlmit`. Note that Bob's allowance in the Market contract for Alice will be `zero(0)` and `100` in `Pearlmit`.\\nWhen Bob tries to borrow an amount equal to his `Pearlmit` allowance, down the borrow logic `_allowedBorrow` is called, in `_allowedBorrow` function, the below requirement passes, since the returned `pearlmitAllowed` for Bob will equal `100` shares\\n```\\n require(allowanceBorrow[from][msg.sender] >= share || pearlmitAllowed >= share, "Market: not approved");\\n```\\n\\nRemember Bob's allowance in the Market contract for Alice is `0`, but `100` in `Pearlmit`, but _allowedBorrow function erroneously attempts to deduct the share from Bob's Market allowance, which will thus result in an underflow revert(0 - 100).\\n```\\n            if (allowanceBorrow[from][msg.sender] != type(uint256).max) {\\n                allowanceBorrow[from][msg.sender] -= share;\\n            }\\n```\\n
After ensuring that the user has got the approval, return when permission from `Pearlmit` is used:\\n```\\n    function _allowedBorrow(address from, uint256 share) internal virtual override {\\n        if (from != msg.sender) {\\n            // TODO review risk of using this\\n            (uint256 pearlmitAllowed,) = penrose.pearlmit().allowance(from, msg.sender, address(yieldBox), collateralId);\\n            require(allowanceBorrow[from][msg.sender] >= share || pearlmitAllowed >= share, "Market: not approved");\\n+            if (pearlmitAllowed != 0) return;\\n            if (allowanceBorrow[from][msg.sender] != type(uint256).max) {\\n                allowanceBorrow[from][msg.sender] -= share;\\n            }\\n        }\\n    }\\n```\\n\\nOr remove support for `Pearlmit` allowance
Although giving a spender allowance via `Pearlmit` will appear to be supported, the spender cannot carry out any borrowing action in the Market.
```\\n    function _allowedBorrow(address from, uint256 share) internal virtual override {\\n        if (from != msg.sender) {\\n            // TODO review risk of using this\\n            (uint256 pearlmitAllowed,) = penrose.pearlmit().allowance(from, msg.sender, address(yieldBox), collateralId);\\n            require(allowanceBorrow[from][msg.sender] >= share || pearlmitAllowed >= share, "Market: not approved");\\n            if (allowanceBorrow[from][msg.sender] != type(uint256).max) {\\n                allowanceBorrow[from][msg.sender] -= share;\\n            }\\n        }\\n    }\\n```\\n