* @notice Protected divest method for exiting a position entered using this contract's `invest` method
* @param _market Address of the market to repay debt to
* @param _recipient Address where any leftover funds should be transferred
* @param _withdrawAmount Amount of Curve receipt tokens to redeem
* @param _excessTokens Quantity to transfer from the caller into this address to ensure
* the borrow can be repaid in full.
* @param _curveMinAmountOut The minAmountOut we expect to receive when removing liquidity from Curve
uint256 _curveMinAmountOut
require(_market == moneyMarket || _market == protectionMarket, "Invalid borrow market");
// 1. Withdraw Curve receipt tokens from from Convex
IConvexRewardManager _convexRewardManager = IConvexRewardManager(convexRewardManager);
_convexRewardManager.withdrawAndUnwrap(_withdrawAmount, false);
// 2. Withdraw from Curve
// There are two kinds of curve zaps -- one requires curve pool to be specified in first argument.
// Approve Curve's depositZap to spend our receipt tokens.
// As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors on the approve
// method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by some
// ERC-20 tokens, such as USDT.
IERC20(curveLpToken).safeApprove(curveDepositZap, 0);
IERC20(curveLpToken).safeApprove(curveDepositZap, type(uint256).max);
ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(
ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(_withdrawAmount, curveIndex, _curveMinAmountOut);
// Pay back as much of the borrow as possible, excess is refunded to `recipient`
executeMaxRepay(_market, address(underlying), _excessTokens);
// Transfer any remaining tokens to the user after paying back borrow
IERC20(underlying).transfer(_recipient, IERC20(underlying).balanceOf(address(this)));
claimRewards(_recipient);