Vulnerability: The protocol does not compatible with token such as USDT because of the Approval Face Protection
Severity: medium

Description:
The protocol does not compatible with token such as USDT because of the Approval Face Protection\\nthe protocol is intended to interact with any ERC20 token and USDT is a common one\\nQ: Which ERC20 tokens do you expect will interact with the smart contracts? The protocol expects to interact with any ERC20.\\nIndividual SetToken's should only interact with ERC20 chosen by the SetToken manager.\\nwhen doing the deleverage\\nfirst, we construct the deleverInfo\\n```\\nActionInfo memory deleverInfo = _createAndValidateActionInfo(\\n  _setToken,\\n  _collateralAsset,\\n  _repayAsset,\\n  _redeemQuantityUnits,\\n  _minRepayQuantityUnits,\\n  _tradeAdapterName,\\n  false\\n );\\n```\\n\\nthen we withdraw from the lending pool, execute trade and repay the borrow token\\n```\\n_withdraw(deleverInfo.setToken, deleverInfo.lendingPool, _collateralAsset, deleverInfo.notionalSendQuantity);\\n\\n        uint256 postTradeReceiveQuantity = _executeTrade(deleverInfo, _collateralAsset, _repayAsset, _tradeData);\\n\\n        uint256 protocolFee = _accrueProtocolFee(_setToken, _repayAsset, postTradeReceiveQuantity);\\n\\n        uint256 repayQuantity = postTradeReceiveQuantity.sub(protocolFee);\\n\\n        _repayBorrow(deleverInfo.setToken, deleverInfo.lendingPool, _repayAsset, repayQuantity);\\n```\\n\\nthis is calling _repayBorrow\\n```\\n/**\\n * @dev Invoke repay from SetToken using AaveV2 library. Burns DebtTokens for SetToken.\\n */\\nfunction _repayBorrow(ISetToken _setToken, ILendingPool _lendingPool, IERC20 _asset, uint256 _notionalQuantity) internal {\\n _setToken.invokeApprove(address(_asset), address(_lendingPool), _notionalQuantity);\\n _setToken.invokeRepay(_lendingPool, address(_asset), _notionalQuantity, BORROW_RATE_MODE);\\n}\\n```\\n\\nthe trade received (quantity - the protocol fee) is used to repay the debt\\nbut the required debt to be required is the (borrowed amount + the interest rate)\\nsuppose the only debt that needs to be repayed is 1000 USDT\\ntrade received (quantity - the protocol) fee is 20000 USDT\\nonly 1000 USDT is used to repay the debt\\nbecause when repaying, the paybackAmount is only the debt amount\\n```\\nuint256 paybackAmount = params.interestRateMode == DataTypes.InterestRateMode.STABLE\\n  ? stableDebt\\n  : variableDebt;\\n```\\n\\nthen when burning the variable debt token\\n```\\nreserveCache.nextScaledVariableDebt = IVariableDebtToken(\\n reserveCache.variableDebtTokenAddress\\n  ).burn(params.onBehalfOf, paybackAmount, reserveCache.nextVariableBorrowIndex);\\n```\\n\\nonly the "payback amount", which is 1000 USDT is transferred to pay the debt,\\nthe excessive leftover amount is (20000 USDT - 1000 USDT) = 19000 USDT\\nbut if we lookback into the repayBack function\\n```\\n/**\\n * @dev Invoke repay from SetToken using AaveV2 library. Burns DebtTokens for SetToken.\\n */\\nfunction _repayBorrow(ISetToken _setToken, ILendingPool _lendingPool, IERC20 _asset, uint256 _notionalQuantity) internal {\\n _setToken.invokeApprove(address(_asset), address(_lendingPool), _notionalQuantity);\\n _setToken.invokeRepay(_lendingPool, address(_asset), _notionalQuantity, BORROW_RATE_MODE);\\n}\\n```\\n\\nthe approved amount is 20000 USDT, but only 1000 USDT approval limit is used, we have 19000 USDT approval limit left\\naccording to\\nSome tokens (e.g. OpenZeppelin) will revert if trying to approve the zero address to spend tokens (i.e. a call to approve(address(0), amt)).\\nIntegrators may need to add special cases to handle this logic if working with such a token.\\nUSDT is such token that subject to approval race condition, without approving 0 first, the second approve after first repay will revert

Impact:
second and following repay borrow will revert if the ERC20 token is subject to approval race condition

Recommended mitigation:
Approval 0 first