Unchecked Return Values - IComptroller exitMarket, enterMarket
`IComptroller.exitMarket()`, `IComptroller.enterMarkets()` may return a non-zero uint on error but none of the Providers check for this error condition. Together with issue 4.10, this might suggest that unchecked return values may be a systemic problem.\\nHere's the upstream implementation:\\n```\\nif (amountOwed != 0) {\\n return fail(Error.NONZERO\\_BORROW\\_BALANCE, FailureInfo.EXIT\\_MARKET\\_BALANCE\\_OWED);\\n}\\n\\n/\\* Fail if the sender is not permitted to redeem all of their tokens \\*/\\nuint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\nif (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT\\_MARKET\\_REJECTION, allowed);\\n}\\n```\\n\\n```\\n /\\*\\*\\n \\* @notice Removes asset from sender's account liquidity calculation\\n \\* @dev Sender must not have an outstanding borrow balance in the asset,\\n \\* or be providing necessary collateral for an outstanding borrow.\\n \\* @param cTokenAddress The address of the asset to be removed\\n \\* @return Whether or not the account successfully exited the market\\n \\*/\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /\\* Get sender tokensHeld and amountOwed underlying from the cToken \\*/\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code\\n\\n /\\* Fail if the sender has a borrow balance \\*/\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO\\_BORROW\\_BALANCE, FailureInfo.EXIT\\_MARKET\\_BALANCE\\_OWED);\\n }\\n\\n /\\* Fail if the sender is not permitted to redeem all of their tokens \\*/\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT\\_MARKET\\_REJECTION, allowed);\\n }\\n```\\n\\nUnchecked return value `exitMarket`\\nAll Providers exhibit the same issue, probably due to code reuse. (also see https://github.com/ConsenSysDiligence/fuji-protocol-audit-2022-02/issues/19). Some examples:\\n```\\nfunction \\_exitCollatMarket(address \\_cyTokenAddress) internal {\\n // Create a reference to the corresponding network Comptroller\\n IComptroller comptroller = IComptroller(\\_getComptrollerAddress());\\n\\n comptroller.exitMarket(\\_cyTokenAddress);\\n}\\n```\\n\\n```\\nfunction \\_exitCollatMarket(address \\_cyTokenAddress) internal {\\n // Create a reference to the corresponding network Comptroller\\n IComptroller comptroller = IComptroller(\\_getComptrollerAddress());\\n\\n comptroller.exitMarket(\\_cyTokenAddress);\\n}\\n```\\n\\n```\\nfunction \\_exitCollatMarket(address \\_cTokenAddress) internal {\\n // Create a reference to the corresponding network Comptroller\\n IComptroller comptroller = IComptroller(\\_getComptrollerAddress());\\n\\n comptroller.exitMarket(\\_cTokenAddress);\\n}\\n```\\n\\n```\\nfunction \\_exitCollatMarket(address \\_cyTokenAddress) internal {\\n // Create a reference to the corresponding network Comptroller\\n IComptroller comptroller = IComptroller(\\_getComptrollerAddress());\\n\\n comptroller.exitMarket(\\_cyTokenAddress);\\n}\\n```\\n\\nUnchecked return value `enterMarkets` (Note that `IComptroller` returns `NO_ERROR` when already joined to `enterMarkets`.\\nAll Providers exhibit the same issue, probably due to code reuse. (also see https://github.com/ConsenSysDiligence/fuji-protocol-audit-2022-02/issues/19). For example:\\n```\\nfunction \\_enterCollatMarket(address \\_cyTokenAddress) internal {\\n // Create a reference to the corresponding network Comptroller\\n IComptroller comptroller = IComptroller(\\_getComptrollerAddress());\\n\\n address[] memory cyTokenMarkets = new address[](1);\\n cyTokenMarkets[0] = \\_cyTokenAddress;\\n comptroller.enterMarkets(cyTokenMarkets);\\n}\\n```\\n
Require that return value is `ERROR.NO_ERROR` or `0`.
```\\nif (amountOwed != 0) {\\n return fail(Error.NONZERO\\_BORROW\\_BALANCE, FailureInfo.EXIT\\_MARKET\\_BALANCE\\_OWED);\\n}\\n\\n/\\* Fail if the sender is not permitted to redeem all of their tokens \\*/\\nuint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\nif (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT\\_MARKET\\_REJECTION, allowed);\\n}\\n```\\n