From 016c8d4370532fbf6927c2b741e4e180172526e0 Mon Sep 17 00:00:00 2001 From: Jeff Wu Date: Fri, 17 Dec 2021 07:57:05 -0800 Subject: [PATCH] allowing more deposit types in borrow spell --- .../mainnet/connectors/notional/helpers.sol | 36 +++++++++++++------ .../mainnet/connectors/notional/main.sol | 29 +++++++++++---- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/contracts/mainnet/connectors/notional/helpers.sol b/contracts/mainnet/connectors/notional/helpers.sol index 84f9b91c..0aceb6e0 100644 --- a/contracts/mainnet/connectors/notional/helpers.sol +++ b/contracts/mainnet/connectors/notional/helpers.sol @@ -213,7 +213,7 @@ contract Helpers is Basic { function getDepositCollateralBorrowAndWithdrawActions( uint16 depositCurrencyId, - bool useUnderlying, + DepositActionType depositAction, uint256 depositAmount, uint16 borrowCurrencyId, uint8 marketIndex, @@ -221,9 +221,29 @@ contract Helpers is Basic { uint32 maxBorrowRate, bool redeemToUnderlying ) internal returns (BalanceActionWithTrades[] memory action) { - // TODO: allow minting nTokens here.... - BalanceActionWithTrades[] - memory actions = new BalanceActionWithTrades[](2); + BalanceActionWithTrades[] memory actions; + bytes32[] memory trades = new bytes32[](1); + trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate); + + if (depositCurrencyId == borrowCurrencyId) { + // In this case the account is likely borrowing against newly minted nTokens + // in the same currency. Technically the other deposit actions may work but + // there's no good reason to borrow against cToken collateral + actions = new BalanceActionWithTrades[](1); + actions[0].actionType = depositAction; + actions[0].currencyId = depositCurrencyId; + actions[0].depositActionAmount = depositAmount; + // Withdraw borrowed amount to wallet + actions[0].withdrawEntireCashBalance = true; + actions[0].redeemToUnderlying = redeemToUnderlying; + actions[0].trades = trades; + + return actions; + } + + // This is the more common case that the account is borrowing against + // collateral in a different currency + actions = new BalanceActionWithTrades[](2); uint256 depositIndex; uint256 borrowIndex; @@ -236,9 +256,7 @@ contract Helpers is Basic { borrowIndex = 0; } - actions[depositIndex].actionType = useUnderlying - ? DepositActionType.DepositUnderlying - : DepositActionType.DepositAsset; + actions[depositIndex].actionType = depositAction; actions[depositIndex].currencyId = depositCurrencyId; actions[depositIndex].depositActionAmount = depositAmount; @@ -247,12 +265,8 @@ contract Helpers is Basic { // Withdraw borrowed amount to wallet actions[borrowIndex].withdrawEntireCashBalance = true; actions[borrowIndex].redeemToUnderlying = redeemToUnderlying; - - bytes32[] memory trades = new bytes32[](1); - trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate); actions[borrowIndex].trades = trades; return actions; } - } diff --git a/contracts/mainnet/connectors/notional/main.sol b/contracts/mainnet/connectors/notional/main.sol index 1a916e47..d85bdfc6 100644 --- a/contracts/mainnet/connectors/notional/main.sol +++ b/contracts/mainnet/connectors/notional/main.sol @@ -455,14 +455,25 @@ abstract contract NotionalResolver is Events, Helpers { } /** - * @notice Deposits some amount of tokens as collateral and borrows + * @notice Deposits some amount of tokens as collateral and borrows. This can be achieved by combining multiple spells but this + * method is more gas efficient by only making a single call to Notional. * @dev Setting the fCash amount and maxBorrowRate are best calculated using the Notional SDK off chain. The amount of fCash * when borrowing is more forgiving compared to lending since generally accounts will over collateralize and dust amounts are * less likely to cause reverts. The Notional SDK will also provide calculations to tell the user what their LTV is for a given * borrowing action. * @param depositCurrencyId notional defined currency id of the collateral to deposit - * @param useUnderlying if true, will accept a deposit collateralin the underlying currency (i.e DAI), if false - * will use the asset currency (i.e. cDAI) + * @param depositAction one of the following values which will define how the collateral is deposited: + * - None: no collateral will be deposited + * - DepositAsset: deposit amount will be specified in asset tokens (i.e. cTokens) + * - DepositUnderlying: deposit amount will be specified in underlying tokens (i.e. DAI) + * - DepositAssetAndMintNToken: deposit amount will be converted to nTokens + * - DepositUnderlyingAndMintNToken: deposit amount will be converted to nTokens + * + * Technically these two deposit types can be used, but there is not a clear reason why they would be used in combination + * with borrowing: + * - RedeemNToken + * - ConvertCashToNToken + * * @param depositAmount amount of cash to deposit as collateral * @param borrowCurrencyId id of the currency to borrow * @param marketIndex the market index to borrow from. This is a number from 1 to 7 which corresponds to the tenor @@ -478,7 +489,7 @@ abstract contract NotionalResolver is Events, Helpers { */ function depositCollateralBorrowAndWithdraw( uint16 depositCurrencyId, - bool useUnderlying, + DepositActionType depositAction, uint256 depositAmount, uint16 borrowCurrencyId, uint8 marketIndex, @@ -492,7 +503,10 @@ abstract contract NotionalResolver is Events, Helpers { payable returns (string memory _eventName, bytes memory _eventParam) { - require(depositCurrencyId != borrowCurrencyId); + bool useUnderlying = ( + depositAction == DepositActionType.DepositUnderlying || + depositAction == DepositActionType.DepositUnderlyingAndMintNToken + ); depositAmount = getDepositAmountAndSetApproval( getId, @@ -504,7 +518,7 @@ abstract contract NotionalResolver is Events, Helpers { BalanceActionWithTrades[] memory actions = getDepositCollateralBorrowAndWithdrawActions( depositCurrencyId, - useUnderlying, + depositAction, depositAmount, borrowCurrencyId, marketIndex, @@ -513,9 +527,10 @@ abstract contract NotionalResolver is Events, Helpers { redeemToUnderlying ); + uint256 msgValue = getMsgValue(depositCurrencyId, useUnderlying, depositAmount); executeTradeActionWithBalanceChange( actions, - getMsgValue(depositCurrencyId, useUnderlying, depositAmount), + msgValue, borrowCurrencyId, redeemToUnderlying, setId