diff --git a/contracts/mainnet/connectors/notional/events.sol b/contracts/mainnet/connectors/notional/events.sol index 4c667956..a6c86119 100644 --- a/contracts/mainnet/connectors/notional/events.sol +++ b/contracts/mainnet/connectors/notional/events.sol @@ -68,6 +68,7 @@ contract Events { ); event LogDepositCollateralBorrowAndWithdraw( + address indexed account, bool useUnderlying, uint256 depositAmount, uint16 borrowCurrencyId, @@ -78,18 +79,12 @@ contract Events { ); event LogWithdrawLend( + address indexed account, uint16 currencyId, uint8 marketIndex, uint88 fCashAmount, uint32 maxBorrowRate ); - event LogRepayBorrow( - uint16 currencyId, - uint8 marketIndex, - int88 netCashToAccount, - uint32 minLendRate - ); - event LogBatchActionRaw(address indexed account); } diff --git a/contracts/mainnet/connectors/notional/main.sol b/contracts/mainnet/connectors/notional/main.sol index 849ee26d..6ebf6e91 100644 --- a/contracts/mainnet/connectors/notional/main.sol +++ b/contracts/mainnet/connectors/notional/main.sol @@ -9,14 +9,15 @@ import {TokenInterface} from "../../common/interfaces.sol"; /** * @title Notional - * @notice Fixed Rate Lending and Borrowing + * @dev Fixed Rate Lending and Borrowing */ abstract contract NotionalResolver is Events, Helpers { using SafeInt256 for int256; /** * @notice Deposit collateral into Notional, this should only be used for reducing risk of - * liquidation. Deposits into Notional are not earning fixed rates, they are earning the cToken + * liquidation. + * @dev Deposits into Notional are not earning fixed rates, they are earning the cToken * lending rate. In order to lend at fixed rates use `depositAndLend` * @param currencyId notional defined currency id to deposit * @param useUnderlying if true, will accept a deposit in the underlying currency (i.e DAI), if false @@ -64,7 +65,7 @@ abstract contract NotionalResolver is Events, Helpers { setUint(setId, assetCashDeposited); - _eventName = "LogDepositCollateral(uint16,bool,uint256,uint256)"; + _eventName = "LogDepositCollateral(address,uint16,bool,uint256,uint256)"; _eventParam = abi.encode( address(this), currencyId, @@ -76,6 +77,7 @@ abstract contract NotionalResolver is Events, Helpers { /** * @notice Withdraw collateral from Notional + * @dev This spell allows users to withdraw collateral from Notional * @param currencyId notional defined currency id to withdraw * @param redeemToUnderlying if true, will redeem the amount withdrawn to the underlying currency (i.e. DAI), * if false, will simply withdraw the asset token (i.e. cDAI) @@ -90,11 +92,17 @@ abstract contract NotionalResolver is Events, Helpers { uint256 withdrawAmount, uint256 getId, uint256 setId - ) external returns (string memory _eventName, bytes memory _eventParam) { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { withdrawAmount = getUint(getId, withdrawAmount); uint88 amountInternalPrecision = withdrawAmount == uint256(-1) ? uint88(getCashBalance(currencyId)) - : uint88(convertToInternal(currencyId, SafeInt256.toInt(withdrawAmount))); + : uint88( + convertToInternal(currencyId, SafeInt256.toInt(withdrawAmount)) + ); uint256 amountWithdrawn = notional.withdraw( currencyId, @@ -115,11 +123,13 @@ abstract contract NotionalResolver is Events, Helpers { } /** - * @dev Claims NOTE tokens and transfers to the address + * @notice Claims NOTE tokens and transfers to the address + * @dev This spell allows users to claim nToken incentives * @param setId the id to set the balance of NOTE tokens claimed */ function claimNOTE(uint256 setId) external + payable returns (string memory _eventName, bytes memory _eventParam) { uint256 notesClaimed = notional.nTokenClaimIncentives(); @@ -146,8 +156,16 @@ abstract contract NotionalResolver is Events, Helpers { uint96 tokensToRedeem, uint256 getId, uint256 setId - ) external returns (string memory _eventName, bytes memory _eventParam) { - tokensToRedeem = getNTokenRedeemAmount(currencyId, tokensToRedeem, getId); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + tokensToRedeem = getNTokenRedeemAmount( + currencyId, + tokensToRedeem, + getId + ); int256 _assetCashChange = notional.nTokenRedeem( address(this), @@ -193,8 +211,16 @@ abstract contract NotionalResolver is Events, Helpers { bool redeemToUnderlying, uint256 getId, uint256 setId - ) external returns (string memory _eventName, bytes memory _eventParam) { - tokensToRedeem = getNTokenRedeemAmount(currencyId, tokensToRedeem, getId); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + tokensToRedeem = getNTokenRedeemAmount( + currencyId, + tokensToRedeem, + getId + ); BalanceAction[] memory action = new BalanceAction[](1); action[0].actionType = DepositActionType.RedeemNToken; @@ -247,8 +273,16 @@ abstract contract NotionalResolver is Events, Helpers { uint88 fCashAmount, uint32 minLendRate, uint256 getId - ) external returns (string memory _eventName, bytes memory _eventParam) { - tokensToRedeem = getNTokenRedeemAmount(currencyId, tokensToRedeem, getId); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + tokensToRedeem = getNTokenRedeemAmount( + currencyId, + tokensToRedeem, + getId + ); BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[]( 1 @@ -276,6 +310,7 @@ abstract contract NotionalResolver is Events, Helpers { /** * @notice Deposit asset or underlying tokens and mint nTokens in a single transaction + * @dev This spell allows users to deposit and mint nTokens (providing liquidity) * @param currencyId notional defined currency id to deposit * @param depositAmount amount of tokens to deposit * @param useUnderlying if true, will accept a deposit in the underlying currency (i.e DAI), if false @@ -310,7 +345,11 @@ abstract contract NotionalResolver is Events, Helpers { // withdraw amount, withdraw cash and redeem to underlying are all 0 and false int256 nTokenBefore = getNTokenBalance(currencyId); - uint256 msgValue = getMsgValue(currencyId, useUnderlying, depositAmount); + uint256 msgValue = getMsgValue( + currencyId, + useUnderlying, + depositAmount + ); notional.batchBalanceAction{value: msgValue}(address(this), action); @@ -336,6 +375,7 @@ abstract contract NotionalResolver is Events, Helpers { /** * @notice Uses existing Notional cash balance (deposits in Notional held as cTokens) and uses them to mint * nTokens. + * @dev This spell allows users to mint nTokens (providing liquidity) from existing cash balance. * @param currencyId notional defined currency id of the cash balance * @param cashBalanceToMint amount of account's cash balance to convert to nTokens * @param getId id of cash balance @@ -348,6 +388,7 @@ abstract contract NotionalResolver is Events, Helpers { uint256 setId ) external + payable returns (string memory _eventName, bytes memory _eventParam) { cashBalanceToMint = getUint(getId, cashBalanceToMint); @@ -437,7 +478,11 @@ abstract contract NotionalResolver is Events, Helpers { trades[0] = encodeLendTrade(marketIndex, fCashAmount, minLendRate); action[0].trades = trades; - uint256 msgValue = getMsgValue(currencyId, useUnderlying, depositAmount); + uint256 msgValue = getMsgValue( + currencyId, + useUnderlying, + depositAmount + ); notional.batchBalanceAndTradeAction{value: msgValue}( address(this), action @@ -479,7 +524,7 @@ abstract contract NotionalResolver is Events, Helpers { * @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 * of the fCash asset to borrow. Tenors are described here: https://docs.notional.finance/notional-v2/quarterly-rolls/tenors - * @param fCashAmount amount of fCash for the account to borrow, this is equal to how much the account must pay + * @param fCashAmount amount of fCash for the account to borrow, this is equal to how much the account must pay * at maturity (principal plus interest). * @param maxBorrowRate the maximum interest rate that the account is willing to borrow at, if set to zero the account will accept * any borrowing rate @@ -504,10 +549,9 @@ abstract contract NotionalResolver is Events, Helpers { payable returns (string memory _eventName, bytes memory _eventParam) { - bool useUnderlying = ( - depositAction == DepositActionType.DepositUnderlying || - depositAction == DepositActionType.DepositUnderlyingAndMintNToken - ); + bool useUnderlying = (depositAction == + DepositActionType.DepositUnderlying || + depositAction == DepositActionType.DepositUnderlyingAndMintNToken); depositAmount = getDepositAmountAndSetApproval( getId, @@ -528,7 +572,11 @@ abstract contract NotionalResolver is Events, Helpers { redeemToUnderlying ); - uint256 msgValue = getMsgValue(depositCurrencyId, useUnderlying, depositAmount); + uint256 msgValue = getMsgValue( + depositCurrencyId, + useUnderlying, + depositAmount + ); executeTradeActionWithBalanceChange( actions, msgValue, diff --git a/scripts/constant/abis.js b/scripts/constant/abis.js index bc1fd8f1..cb62ccfb 100644 --- a/scripts/constant/abis.js +++ b/scripts/constant/abis.js @@ -8,7 +8,6 @@ module.exports = { basic: require("./abi/connectors/basic.json"), auth: require("./abi/connectors/auth.json"), "INSTAPOOL-A": require("./abi/connectors/instapool.json"), - "BASIC-A": require("./abi/connectors/basic.json") }, basic: { erc20: require("./abi/basics/erc20.json"), diff --git a/test/notional/notional.helpers.js b/test/notional/notional.helpers.js index a82e989e..a31a07c4 100644 --- a/test/notional/notional.helpers.js +++ b/test/notional/notional.helpers.js @@ -140,19 +140,6 @@ const withdrawLend = async (dsa, authority, referrer, currencyId, marketIndex, f await tx.wait() }; -const depositERC20 = async (dsa, authority, referrer, token, amount) => { - const spells = [ - { - connector: "BASIC-A", - method: "deposit", - args: [token, amount, 0, 0] - } - ]; - - const tx = await dsa.connect(authority).cast(...encodeSpells(spells), referrer.address); - await tx.wait() -}; - module.exports = { depositCollteral, depositAndMintNToken, @@ -162,6 +149,5 @@ module.exports = { redeemNTokenRaw, redeemNTokenAndWithdraw, redeemNTokenAndDeleverage, - depositCollateralBorrowAndWithdraw, - depositERC20 + depositCollateralBorrowAndWithdraw }; diff --git a/test/notional/notional.test.js b/test/notional/notional.test.js index f7a3a841..573bf307 100644 --- a/test/notional/notional.test.js +++ b/test/notional/notional.test.js @@ -133,9 +133,7 @@ describe("Notional", function () { it("test_deposit_ETH_asset", async function () { const depositAmount = ethers.utils.parseUnits("1", 8); - await cethToken.connect(cethWhale).transfer(wallet0.address, depositAmount); - await cethToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cethToken.address, depositAmount); + await cethToken.connect(cethWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, ETH_ID, depositAmount, false); const bal = await notional.callStatic.getAccountBalance(ETH_ID, dsaWallet0.address); // balance in internal asset precision @@ -145,9 +143,7 @@ describe("Notional", function () { it("test_deposit_DAI_underlying", async function () { const depositAmount = ethers.utils.parseUnits("1000", 18); - await daiToken.connect(daiWhale).transfer(wallet0.address, depositAmount); - await daiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, daiToken.address, depositAmount); + await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, true); const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address); // balance in internal asset precision @@ -157,9 +153,7 @@ describe("Notional", function () { it("test_deposit_DAI_asset", async function () { const depositAmount = ethers.utils.parseUnits("1000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false); const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address); // balance in internal asset precision @@ -195,9 +189,7 @@ describe("Notional", function () { it("test_deposit_ETH_asset_and_lend", async function () { const depositAmount = ethers.utils.parseUnits("1", 8); - await cethToken.connect(cethWhale).transfer(wallet0.address, depositAmount); - await cethToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cethToken.address, depositAmount); + await cethToken.connect(cethWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, ETH_ID, false, depositAmount, MARKET_3M, 0.01e8, 0); const portfolio = await notional.getAccountPortfolio(dsaWallet0.address); expect(portfolio.length, "expect 1 lending position").to.be.equal(1); @@ -206,9 +198,7 @@ describe("Notional", function () { it("test_deposit_DAI_underlying_and_lend", async function () { const depositAmount = ethers.utils.parseUnits("1000", 18); - await daiToken.connect(daiWhale).transfer(wallet0.address, depositAmount); - await daiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, daiToken.address, depositAmount); + await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, DAI_ID, true, depositAmount, MARKET_3M, 100e8, 0); const portfolio = await notional.getAccountPortfolio(dsaWallet0.address); expect(portfolio.length, "expect 1 lending position").to.be.equal(1); @@ -217,9 +207,7 @@ describe("Notional", function () { it("test_deposit_DAI_asset_and_lend", async function () { const depositAmount = ethers.utils.parseUnits("1000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, DAI_ID, false, depositAmount, MARKET_3M, 10e8, 0); const portfolio = await notional.getAccountPortfolio(dsaWallet0.address); expect(portfolio.length, "expect 1 lending position").to.be.equal(1); @@ -275,9 +263,7 @@ describe("Notional", function () { it("test_deposit_DAI_underlying_and_borrow_ETH", async function () { const depositAmount = ethers.utils.parseUnits("20000", 18); - await daiToken.connect(daiWhale).transfer(wallet0.address, depositAmount); - await daiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, daiToken.address, depositAmount); + await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollateralBorrowAndWithdraw( dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true ); @@ -289,9 +275,7 @@ describe("Notional", function () { it("test_deposit_DAI_asset_and_borrow_ETH", async function () { const depositAmount = ethers.utils.parseUnits("1000000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollateralBorrowAndWithdraw( dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_ASSET, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true ); @@ -303,9 +287,7 @@ describe("Notional", function () { it("test_mint_nDAI_underlying_and_borrow_ETH", async function () { const depositAmount = ethers.utils.parseUnits("20000", 18); - await daiToken.connect(daiWhale).transfer(wallet0.address, depositAmount); - await daiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, daiToken.address, depositAmount); + await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollateralBorrowAndWithdraw( dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING_MINT_NTOKEN, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true ); @@ -317,9 +299,7 @@ describe("Notional", function () { it("test_mint_nDAI_asset_and_borrow_ETH", async function () { const depositAmount = ethers.utils.parseUnits("1000000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollateralBorrowAndWithdraw( dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_ASSET_MINT_NTOKEN, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true ); @@ -361,9 +341,7 @@ describe("Notional", function () { it("test_redeem_DAI_raw", async function () { const depositAmount = ethers.utils.parseUnits("1000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false); await helpers.redeemNTokenRaw(dsaWallet0, wallet0, wallet1, DAI_ID, true, MaxUint96) const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address); @@ -373,9 +351,7 @@ describe("Notional", function () { it("test_redeem_DAI_and_withdraw_redeem", async function () { const depositAmount = ethers.utils.parseUnits("1000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false); await helpers.redeemNTokenAndWithdraw(dsaWallet0, wallet0, wallet1, DAI_ID, MaxUint96, ethers.constants.MaxUint256, true); const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address); @@ -385,9 +361,7 @@ describe("Notional", function () { it("test_redeem_DAI_and_withdraw_no_redeem", async function () { const depositAmount = ethers.utils.parseUnits("1000", 8); - await cdaiToken.connect(cdaiWhale).transfer(wallet0.address, depositAmount); - await cdaiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, cdaiToken.address, depositAmount); + await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false); expect(await cdaiToken.balanceOf(dsaWallet0.address)).to.be.equal(ethers.utils.parseEther("0")); await helpers.redeemNTokenAndWithdraw(dsaWallet0, wallet0, wallet1, DAI_ID, MaxUint96, ethers.constants.MaxUint256, false); @@ -402,9 +376,7 @@ describe("Notional", function () { it("test_redeem_DAI_and_deleverage", async function () { const depositAmount = ethers.utils.parseUnits("20000", 18); - await daiToken.connect(daiWhale).transfer(wallet0.address, depositAmount); - await daiToken.connect(wallet0).approve(dsaWallet0.address, ethers.constants.MaxUint256); - await helpers.depositERC20(dsaWallet0, wallet0, wallet1, daiToken.address, depositAmount); + await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount); await helpers.depositCollateralBorrowAndWithdraw( dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true );