Vulnerability: Unchecked Return Values - ICErc20 repayBorrow
Severity: high

Description:
`ICErc20.repayBorrow` returns a non-zero uint on error. Multiple providers do not check for this error condition and might return `success` even though `repayBorrow` failed, returning an error code.\\nThis can potentially allow a malicious user to call `paybackAndWithdraw()` while not repaying by causing an error in the sub-call to `Compound.repayBorrow()`, which ends up being silently ignored. Due to the missing success condition check, execution continues normally with `_internalWithdraw()`.\\nAlso, see issue 4.5.\\n```\\nfunction repayBorrow(uint256 repayAmount) external returns (uint256);\\n```\\n\\nThe method may return an error due to multiple reasons:\\n```\\nfunction repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO\\_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY\\_BORROW\\_ACCRUE\\_INTEREST\\_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n}\\n```\\n\\n```\\nif (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER\\_REJECTION, FailureInfo.REPAY\\_BORROW\\_COMPTROLLER\\_REJECTION, allowed), 0);\\n}\\n\\n/\\* Verify market's block number equals current block number \\*/\\nif (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET\\_NOT\\_FRESH, FailureInfo.REPAY\\_BORROW\\_FRESHNESS\\_CHECK), 0);\\n}\\n\\nRepayBorrowLocalVars memory vars;\\n\\n/\\* We remember the original borrowerIndex for verification purposes \\*/\\nvars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n/\\* We fetch the amount the borrower owes, with accumulated interest \\*/\\n(vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\nif (vars.mathErr != MathError.NO\\_ERROR) {\\n return (failOpaque(Error.MATH\\_ERROR, FailureInfo.REPAY\\_BORROW\\_ACCUMULATED\\_BALANCE\\_CALCULATION\\_FAILED, uint(vars.mathErr)), 0);\\n}\\n```\\n\\nMultiple providers, here are some examples:\\n```\\n // Check there is enough balance to pay\\n require(erc20token.balanceOf(address(this)) >= \\_amount, "Not-enough-token");\\n erc20token.univApprove(address(cyTokenAddr), \\_amount);\\n cyToken.repayBorrow(\\_amount);\\n}\\n```\\n\\n```\\nrequire(erc20token.balanceOf(address(this)) >= \\_amount, "Not-enough-token");\\nerc20token.univApprove(address(cyTokenAddr), \\_amount);\\ncyToken.repayBorrow(\\_amount);\\n```\\n\\n```\\nif (\\_isETH(\\_asset)) {\\n // Create a reference to the corresponding cToken contract\\n ICEth cToken = ICEth(cTokenAddr);\\n\\n cToken.repayBorrow{ value: msg.value }();\\n} else {\\n // Create reference to the ERC20 contract\\n IERC20 erc20token = IERC20(\\_asset);\\n\\n // Create a reference to the corresponding cToken contract\\n ICErc20 cToken = ICErc20(cTokenAddr);\\n\\n // Check there is enough balance to pay\\n require(erc20token.balanceOf(address(this)) >= \\_amount, "Not-enough-token");\\n erc20token.univApprove(address(cTokenAddr), \\_amount);\\n cToken.repayBorrow(\\_amount);\\n}\\n```\\n

Impact:

Recommended mitigation:
Check for `cyToken.repayBorrow(_amount) != 0` or `Error.NO_ERROR`.