From bebd120d2177554f4b6f946fbac30021fb9d13e9 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 3 Aug 2022 21:51:00 +0530 Subject: [PATCH 01/24] basic contract setup --- .../connectors/euler-import/helpers.sol | 160 ++++++++++++++++++ .../connectors/euler-import/interface.sol | 55 ++++++ .../mainnet/connectors/euler-import/main.sol | 64 +++++++ 3 files changed, 279 insertions(+) create mode 100644 contracts/mainnet/connectors/euler-import/helpers.sol create mode 100644 contracts/mainnet/connectors/euler-import/interface.sol create mode 100644 contracts/mainnet/connectors/euler-import/main.sol diff --git a/contracts/mainnet/connectors/euler-import/helpers.sol b/contracts/mainnet/connectors/euler-import/helpers.sol new file mode 100644 index 00000000..42824fdd --- /dev/null +++ b/contracts/mainnet/connectors/euler-import/helpers.sol @@ -0,0 +1,160 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; +import { TokenInterface, AccountInterface } from "../../common/interfaces.sol"; +import { Basic } from "../../common/basic.sol"; +import "./interface.sol"; + +contract EulerHelpers is Basic { + + IEulerMarkets internal constant markets = + IEulerMarkets(0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3); + + IEulerExecute internal constant eulerExec = IEulerExecute(0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80); + + function getSubAccountAddress(address primary, uint256 subAccountId) + public + pure + returns (address) + { + require(subAccountId < 256, "sub-account-id-too-big"); + return address(uint160(primary) ^ uint160(subAccountId)); + } + + struct ImportInputData { + address[] supplyTokens; + address[] borrowTokens; + } + + struct ImportData { + address[] _supplyTokens; + address[] _borrowTokens; + EulerTokenInterface[] eTokens; + EulerTokenInterface[] dTokens; + uint256[] supplyAmts; + uint256[] borrowAmts; + } + + function getSupplyAmounts( + address userAccount, + ImportInputData memory inputData, + ImportData memory data + ) internal view returns (ImportData memory) { + data.supplyAmts = new uint256[](inputData.supplyTokens.length); + data._supplyTokens = new address[](inputData.supplyTokens.length); + data.eTokens = new EulerTokenInterface[](inputData.supplyTokens.length); + + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + for (uint256 j = i; j < inputData.supplyTokens.length; j++) { + if (j != i) { + require( + inputData.supplyTokens[i] != inputData.supplyTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + address _token = inputData.supplyTokens[i] == ethAddr + ? wethAddr + : inputData.supplyTokens[i]; + data._supplyTokens[i] = _token; + data.eTokens[i] = EulerTokenInterface(markets.underlyingToEToken(_token)); + data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount); + } + + return data; + } + + function getBorrowAmounts( + address userAccount,//user's EOA sub-account address + ImportInputData memory inputData, + ImportData memory data + ) internal view returns (ImportData memory) { + if (inputData.borrowTokens.length > 0) { + data._borrowTokens = new address[](inputData.borrowTokens.length); + data.borrowAmts = new uint256[]( + inputData.borrowTokens.length + ); + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + for (uint256 j = i; j < inputData.borrowTokens.length; j++) { + if (j != i) { + require( + inputData.borrowTokens[i] != + inputData.borrowTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + address _token = inputData.borrowTokens[i] == ethAddr + ? wethAddr + : inputData.borrowTokens[i]; + + data._borrowTokens[i] = _token; + data.dTokens[i] = EulerTokenInterface(markets.underlyingToDToken(_token)); + data.borrowAmts[i] = data.dTokens[i].balanceOf(userAccount); + } + } + return data; + } + +//transfer and enter market + function _TransferEtokens( + uint256 _length, + EulerTokenInterface[] memory etokenContracts, + uint256[] memory amts, + address[] memory tokens, + bool[] memory enterMarket, + address userAccountFrom, + address userAccountTo, + uint targetId + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + etokenContracts[i].transferFrom( + userAccountFrom, + userAccountTo, + _amt + ), + "allowance?"//change + ); + + if (enterMarket[i]) { + markets.enterMarket(targetId, tokens[i]); + } else { + markets.exitMarket(targetId, tokens[i]); + } + } + } + } + + function _TransferDtokens( + uint256 _length, + EulerTokenInterface[] memory dtokenContracts, + uint256[] memory amts, + address[] memory tokens, + address eoaIdFrom, + address dsaIdTo + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + dtokenContracts[i].transferFrom( + eoaIdFrom, + dsaIdTo, + _amt + ), + "debt-transfer-failed?" + ); + } + } + } + + + +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/euler-import/interface.sol b/contracts/mainnet/connectors/euler-import/interface.sol new file mode 100644 index 00000000..a62a860b --- /dev/null +++ b/contracts/mainnet/connectors/euler-import/interface.sol @@ -0,0 +1,55 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +interface EulerTokenInterface { + + function balanceOf(address _user) external view returns (uint256); + + function transferFrom( + address, + address, + uint256 + ) external returns (bool); + + function allowance(address, address) external returns (uint256); +} + +interface IEulerMarkets { + function enterMarket(uint256 subAccountId, address newMarket) external; + + function getEnteredMarkets(address account) + external + view + returns (address[] memory); + + function exitMarket(uint256 subAccountId, address oldMarket) external; + + function underlyingToEToken(address underlying) + external + view + returns (address); + + function underlyingToDToken(address underlying) + external + view + returns (address); +} + +interface IEulerExecute { + + struct EulerBatchItem { + bool allowError; + address proxyAddr; + bytes data; + } + + struct EulerBatchItemResponse { + bool success; + bytes result; + } + + function batchDispatch(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) external returns (EulerBatchItemResponse[] memory); + + function deferLiquidityCheck(address account, bytes memory data) external; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol new file mode 100644 index 00000000..b9dfe0db --- /dev/null +++ b/contracts/mainnet/connectors/euler-import/main.sol @@ -0,0 +1,64 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; +import "./helpers.sol"; + +contract EulerImport is EulerHelpers { + + function importEuler( + address userAccount,//EOA address + uint256 sourceId, + uint256 targetId, + bool[] memory enterMarket, + ImportInputData memory inputData + ) + external + payable + { + _importEuler(userAccount, sourceId, targetId, inputData, enterMarket); + } + + function _importEuler( + address userAccount,//EOA address + uint256 sourceId, + uint256 targetId, + ImportInputData memory inputData, + bool[] memory enterMarket + ) + internal + { + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); + require(enterMarket.length == inputData.supplyTokens.length, "lengths-not-same"); + + address _sourceAccount = getSubAccountAddress(userAccount, sourceId); //User's EOA sub-account address + address _targetAccount = getSubAccountAddress(address(this), targetId); + + ImportData memory data; + + data = getBorrowAmounts(_sourceAccount, inputData, data); + data = getSupplyAmounts(_targetAccount, inputData, data); + + _TransferEtokens( + data._supplyTokens.length, + data.eTokens, + data.supplyAmts, + data._supplyTokens, + enterMarket, + _sourceAccount, + _targetAccount + ); + + _TransferDtokens( + data._borrowTokens.length, + data.dTokens, + data.borrowAmts, + data._borrowTokens, + _sourceAccount, + _targetAccount + ); + } +} From 0870b9b83a72d974a4af297d294492e02b5d486c Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 3 Aug 2022 22:28:01 +0530 Subject: [PATCH 02/24] added defer liquidity and events --- .../mainnet/connectors/euler-import/events.sol | 16 ++++++++++++++++ .../mainnet/connectors/euler-import/main.sol | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 contracts/mainnet/connectors/euler-import/events.sol diff --git a/contracts/mainnet/connectors/euler-import/events.sol b/contracts/mainnet/connectors/euler-import/events.sol new file mode 100644 index 00000000..e5904823 --- /dev/null +++ b/contracts/mainnet/connectors/euler-import/events.sol @@ -0,0 +1,16 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +contract Events { + event LogEulerImport( + address indexed user, + uint256 indexed sourceId, + uint256 indexed targetId, + address[] supplyTokens, + address[] borrowTokens, + uint256[] supplyAmts, + uint256[] borrowAmts, + bool[] enterMarket + ); +} diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol index b9dfe0db..b3769281 100644 --- a/contracts/mainnet/connectors/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler-import/main.sol @@ -14,8 +14,9 @@ contract EulerImport is EulerHelpers { ) external payable + returns (string memory _eventName, bytes memory _eventParam) { - _importEuler(userAccount, sourceId, targetId, inputData, enterMarket); + (_eventName, _eventParam) = _importEuler(userAccount, sourceId, targetId, inputData, enterMarket); } function _importEuler( @@ -26,6 +27,7 @@ contract EulerImport is EulerHelpers { bool[] memory enterMarket ) internal + returns (string memory _eventName, bytes memory _eventParam) { require( AccountInterface(address(this)).isAuth(userAccount), @@ -41,6 +43,8 @@ contract EulerImport is EulerHelpers { data = getBorrowAmounts(_sourceAccount, inputData, data); data = getSupplyAmounts(_targetAccount, inputData, data); + + IExec(exec).deferLiquidityCheck(_sourceAccount, bytes(0)); _TransferEtokens( data._supplyTokens.length, @@ -60,5 +64,17 @@ contract EulerImport is EulerHelpers { _sourceAccount, _targetAccount ); + + _eventName = "LogEulerImport(address,uint256,uint256,address[],address[],uint256[],uint256[],bool[])"; + _eventParam = abi.encode( + userAccount, + sourceId, + targetId, + inputData.supplyTokens, + inputData.borrowTokens, + data.supplyAmts, + data.borrowAmts, + enterMarket + ); } } From 6b18e337c7e7ab90ec814bee04ee2220f2f9ab63 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 3 Aug 2022 23:02:08 +0530 Subject: [PATCH 03/24] Added natspec comments --- .../connectors/euler-import/helpers.sol | 12 ++++++++++ .../mainnet/connectors/euler-import/main.sol | 23 +++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/contracts/mainnet/connectors/euler-import/helpers.sol b/contracts/mainnet/connectors/euler-import/helpers.sol index 42824fdd..26f24831 100644 --- a/contracts/mainnet/connectors/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler-import/helpers.sol @@ -7,11 +7,23 @@ import "./interface.sol"; contract EulerHelpers is Basic { + /** + * @dev Euler's Market Module + */ IEulerMarkets internal constant markets = IEulerMarkets(0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3); + /** + * @dev Euler's Execution Module + */ IEulerExecute internal constant eulerExec = IEulerExecute(0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80); + /** + * @dev Compute sub account address. + * @notice Compute sub account address from sub-account id + * @param primary primary address + * @param subAccountId sub-account id whose address needs to be computed + */ function getSubAccountAddress(address primary, uint256 subAccountId) public pure diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol index b3769281..2c4c0e89 100644 --- a/contracts/mainnet/connectors/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler-import/main.sol @@ -5,12 +5,21 @@ import "./helpers.sol"; contract EulerImport is EulerHelpers { + /** + * @dev Import Euler position. + * @notice Import EOA's Euler subaccount position to DSA's Euler subaccount + * @param userAccount The address of the EOA from which position will be imported + * @param sourceId EOA sub-account id from which position be be imported + * @param targetId DSA sub-account id + * @param inputData The struct containing all the neccessary input data + * @param enterMarket The boolean array to enable market in the imported position + */ function importEuler( - address userAccount,//EOA address + address userAccount, uint256 sourceId, uint256 targetId, - bool[] memory enterMarket, - ImportInputData memory inputData + ImportInputData memory inputData, + bool[] memory enterMarket ) external payable @@ -20,7 +29,7 @@ contract EulerImport is EulerHelpers { } function _importEuler( - address userAccount,//EOA address + address userAccount, uint256 sourceId, uint256 targetId, ImportInputData memory inputData, @@ -36,7 +45,7 @@ contract EulerImport is EulerHelpers { require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); require(enterMarket.length == inputData.supplyTokens.length, "lengths-not-same"); - address _sourceAccount = getSubAccountAddress(userAccount, sourceId); //User's EOA sub-account address + address _sourceAccount = getSubAccountAddress(userAccount, sourceId); address _targetAccount = getSubAccountAddress(address(this), targetId); ImportData memory data; @@ -78,3 +87,7 @@ contract EulerImport is EulerHelpers { ); } } + +contract ConnectV2EulerImport is EulerImport { + string public constant name = "Euler-import-v1.0"; +} From 21cc81553c26e40e8042e00aa404ca8ddd708526 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 4 Aug 2022 09:41:43 +0800 Subject: [PATCH 04/24] minor update --- contracts/mainnet/connectors/euler-import/helpers.sol | 2 +- contracts/mainnet/connectors/euler-import/main.sol | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/mainnet/connectors/euler-import/helpers.sol b/contracts/mainnet/connectors/euler-import/helpers.sol index 26f24831..e445604c 100644 --- a/contracts/mainnet/connectors/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler-import/helpers.sol @@ -121,7 +121,7 @@ contract EulerHelpers is Basic { bool[] memory enterMarket, address userAccountFrom, address userAccountTo, - uint targetId + uint256 targetId ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol index 2c4c0e89..fe00c5d0 100644 --- a/contracts/mainnet/connectors/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler-import/main.sol @@ -53,7 +53,7 @@ contract EulerImport is EulerHelpers { data = getBorrowAmounts(_sourceAccount, inputData, data); data = getSupplyAmounts(_targetAccount, inputData, data); - IExec(exec).deferLiquidityCheck(_sourceAccount, bytes(0)); + IEulerExecute(eulerExec).deferLiquidityCheck(_sourceAccount, "0x0"); _TransferEtokens( data._supplyTokens.length, @@ -62,7 +62,8 @@ contract EulerImport is EulerHelpers { data._supplyTokens, enterMarket, _sourceAccount, - _targetAccount + _targetAccount, + targetId ); _TransferDtokens( From 5682362f3407c289ce48fbced9ea41bb11d5fc58 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 5 Aug 2022 00:20:17 +0800 Subject: [PATCH 05/24] added onDeferredLiquidityCheck --- .../connectors/euler-import/helpers.sol | 23 ++++++------ .../mainnet/connectors/euler-import/main.sol | 36 ++++++++++++------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/contracts/mainnet/connectors/euler-import/helpers.sol b/contracts/mainnet/connectors/euler-import/helpers.sol index e445604c..19de35af 100644 --- a/contracts/mainnet/connectors/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler-import/helpers.sol @@ -83,13 +83,14 @@ contract EulerHelpers is Basic { ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { - if (inputData.borrowTokens.length > 0) { - data._borrowTokens = new address[](inputData.borrowTokens.length); - data.borrowAmts = new uint256[]( - inputData.borrowTokens.length - ); - for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { - for (uint256 j = i; j < inputData.borrowTokens.length; j++) { + uint _borrowTokensLength = inputData.borrowTokens.length; + + if (_borrowTokensLength > 0) { + data._borrowTokens = new address[](_borrowTokensLength); + data.dTokens = new EulerTokenInterface[](_borrowTokensLength); + data.borrowAmts = new uint256[](_borrowTokensLength); + for (uint256 i = 0; i < _borrowTokensLength; i++) { + for (uint256 j = i; j < _borrowTokensLength; j++) { if (j != i) { require( inputData.borrowTokens[i] != @@ -99,7 +100,8 @@ contract EulerHelpers is Basic { } } } - for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + + for (uint256 i = 0; i < _borrowTokensLength; i++) { address _token = inputData.borrowTokens[i] == ethAddr ? wethAddr : inputData.borrowTokens[i]; @@ -166,7 +168,4 @@ contract EulerHelpers is Basic { } } } - - - -} \ No newline at end of file +} diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol index fe00c5d0..d54ecb45 100644 --- a/contracts/mainnet/connectors/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler-import/main.sol @@ -53,7 +53,29 @@ contract EulerImport is EulerHelpers { data = getBorrowAmounts(_sourceAccount, inputData, data); data = getSupplyAmounts(_targetAccount, inputData, data); - IEulerExecute(eulerExec).deferLiquidityCheck(_sourceAccount, "0x0"); + eulerExec.deferLiquidityCheck(_sourceAccount, abi.encode(data, enterMarket, _sourceAccount, _targetAccount, targetId)); + + _eventName = "LogEulerImport(address,uint256,uint256,address[],address[],uint256[],uint256[],bool[])"; + _eventParam = abi.encode( + userAccount, + sourceId, + targetId, + inputData.supplyTokens, + inputData.borrowTokens, + data.supplyAmts, + data.borrowAmts, + enterMarket + ); + } + + function onDeferredLiquidityCheck(bytes memory encodedData) external { + ( + ImportData memory data, + bool[] memory enterMarket, + address _sourceAccount, + address _targetAccount, + uint targetId + ) = abi.decode(encodedData, (ImportData, bool[], address, address, uint)); _TransferEtokens( data._supplyTokens.length, @@ -74,18 +96,6 @@ contract EulerImport is EulerHelpers { _sourceAccount, _targetAccount ); - - _eventName = "LogEulerImport(address,uint256,uint256,address[],address[],uint256[],uint256[],bool[])"; - _eventParam = abi.encode( - userAccount, - sourceId, - targetId, - inputData.supplyTokens, - inputData.borrowTokens, - data.supplyAmts, - data.borrowAmts, - enterMarket - ); } } From b5675925c8f807da211bb3d61cc0956a35170163 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 5 Aug 2022 00:22:38 +0800 Subject: [PATCH 06/24] Added import testcases --- .../mainnet/euler-import/euler-import.test.ts | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 test/mainnet/euler-import/euler-import.test.ts diff --git a/test/mainnet/euler-import/euler-import.test.ts b/test/mainnet/euler-import/euler-import.test.ts new file mode 100644 index 00000000..fd3b10b1 --- /dev/null +++ b/test/mainnet/euler-import/euler-import.test.ts @@ -0,0 +1,188 @@ +import { expect } from "chai"; +import hre from "hardhat"; +import { abis } from "../../../scripts/constant/abis"; +import { addresses } from "../../../scripts/tests/mainnet/addresses"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { ConnectV2EulerImport__factory, ConnectV2Euler__factory, IERC20__factory } from "../../../typechain"; +import { parseEther, parseUnits } from "@ethersproject/units"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +const { ethers } = hre; +import type { Signer, Contract } from "ethers"; +import { BigNumber } from "bignumber.js"; + +const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' +const ACC_DAI = '0xcd6Eb888e76450eF584E8B51bB73c76ffBa21FF2' +const Dai = parseUnits('50', 18) + +const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' +const ACC_WETH = '0x05547D4e1A2191B91510Ea7fA8555a2788C70030' +const Weth = parseUnits('50', 18) + +const token_weth = new ethers.Contract( + WETH, + [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}], + ethers.provider, + ) + + const token_dai = new ethers.Contract( + DAI, + [{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}], + ethers.provider, + ) + + + const eTokensABI = [ + "function approve(address, uint256) public", + "function balanceOf(address account) public view returns (uint256)", + "function allowance(address, address) public returns (uint256)", + "function deposit(uint256,uint256) public", +]; + +const dTokensABI = [ + "function balanceOf(address account) public view returns (uint256)", + "function borrow(uint256,uint256) public" +]; + +const marketsABI = [ + "function enterMarket(uint256,address) public", + "function underlyingToEToken(address) public view returns (address)", + "function underlyingToDToken(address) public view returns (address)" +] + +const eWethAddress = "0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D"; +const eWethContract = new ethers.Contract(eWethAddress, eTokensABI); + +const dDaiAddress = '0x6085Bc95F506c326DCBCD7A6dd6c79FBc18d4686'; +const dDaiContract = new ethers.Contract(dDaiAddress, dTokensABI); + +const euler_mainnet = '0x27182842E098f60e3D576794A5bFFb0777E025d3' +const euler_markets = '0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3' +const marketsContract = new ethers.Contract(euler_markets, marketsABI); + + +describe("Euler", function () { + const connectorName = "EULER-IMPORT-TEST-A"; + let connector: any; + + let wallet0: Signer, wallet1:Signer; + let dsaWallet0: any; + let instaConnectorsV2: Contract; + let masterSigner: Signer; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 15178000, + }, + }, + ], + }); + [wallet0, wallet1] = await ethers.getSigners(); + + await hre.network.provider.send("hardhat_setBalance", [ACC_WETH, ethers.utils.parseEther("10").toHexString()]); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_WETH] + }); + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(wallet0.getAddress(), ethers.utils.parseEther("8")); + console.log("weth transferred to wallet0"); + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt( + abis.core.connectorsV2, + addresses.core.connectorsV2 + ); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2EulerImport__factory, + signer: masterSigner, + connectors: instaConnectorsV2, + }); + console.log("Connector address", connector.address); + }); + + it("should have contracts deployed", async () => { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.getAddress()); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: parseEther("10"), + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( + parseEther("10") + ); + }); + + describe("Create Euler position", async () => { + it("Should create Euler position of WETH(collateral) and DAI(debt)", async () => { + // approve WETH to euler + await token_weth.connect(wallet0).approve(euler_mainnet, Weth); + console.log("Approved WETH"); + + //deposit WETH in euler + await eWethContract.connect(wallet0).deposit("0", parseUnits('2', 18));//todo: check balance + console.log("Supplied WETH on Euler"); + + // enter WETH market + await marketsContract.connect(wallet0).enterMarket("0", WETH); + console.log("Entered market for weth"); + + //borrow DAI from Euler + await dDaiContract.connect(wallet0).borrow("0", Dai); + console.log("Borrowed DAI from Euler"); + }); + + it("Should check created position of user", async () => { + expect(await token_dai.connect(wallet0).balanceOf(wallet0.getAddress())).to.be.gte( + new BigNumber(50).multipliedBy(1e18).toString() + ); + }); + }); + + describe("Euler position migration", async () => { + + it("Should migrate euler position", async () => { + const spells = [ + { + connector: "EULER-IMPORT-TEST-A", + method: "importEuler", + args: [ + (await wallet0.getAddress()).toString(), + "0", + "0", + [[WETH], [DAI]], + ["true"] + ] + }, + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.getAddress()); + const receipt = await tx.wait(); + }); + }) +}); +}) \ No newline at end of file From e0882cb8300931cc1a4f6bdc41d2546c6648da68 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 25 Aug 2022 05:26:44 +0530 Subject: [PATCH 07/24] new fixes in import --- .../connectors/euler-import/events.sol | 16 -- .../mainnet/connectors/euler-import/main.sol | 104 ------------ .../connectors/euler/euler-import/events.sol | 15 ++ .../{ => euler}/euler-import/helpers.sol | 64 +------- .../{ => euler}/euler-import/interface.sol | 4 +- .../connectors/euler/euler-import/main.sol | 150 ++++++++++++++++++ 6 files changed, 172 insertions(+), 181 deletions(-) delete mode 100644 contracts/mainnet/connectors/euler-import/events.sol delete mode 100644 contracts/mainnet/connectors/euler-import/main.sol create mode 100644 contracts/mainnet/connectors/euler/euler-import/events.sol rename contracts/mainnet/connectors/{ => euler}/euler-import/helpers.sol (69%) rename contracts/mainnet/connectors/{ => euler}/euler-import/interface.sol (92%) create mode 100644 contracts/mainnet/connectors/euler/euler-import/main.sol diff --git a/contracts/mainnet/connectors/euler-import/events.sol b/contracts/mainnet/connectors/euler-import/events.sol deleted file mode 100644 index e5904823..00000000 --- a/contracts/mainnet/connectors/euler-import/events.sol +++ /dev/null @@ -1,16 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; -pragma experimental ABIEncoderV2; - -contract Events { - event LogEulerImport( - address indexed user, - uint256 indexed sourceId, - uint256 indexed targetId, - address[] supplyTokens, - address[] borrowTokens, - uint256[] supplyAmts, - uint256[] borrowAmts, - bool[] enterMarket - ); -} diff --git a/contracts/mainnet/connectors/euler-import/main.sol b/contracts/mainnet/connectors/euler-import/main.sol deleted file mode 100644 index d54ecb45..00000000 --- a/contracts/mainnet/connectors/euler-import/main.sol +++ /dev/null @@ -1,104 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; -pragma experimental ABIEncoderV2; -import "./helpers.sol"; - -contract EulerImport is EulerHelpers { - - /** - * @dev Import Euler position. - * @notice Import EOA's Euler subaccount position to DSA's Euler subaccount - * @param userAccount The address of the EOA from which position will be imported - * @param sourceId EOA sub-account id from which position be be imported - * @param targetId DSA sub-account id - * @param inputData The struct containing all the neccessary input data - * @param enterMarket The boolean array to enable market in the imported position - */ - function importEuler( - address userAccount, - uint256 sourceId, - uint256 targetId, - ImportInputData memory inputData, - bool[] memory enterMarket - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - (_eventName, _eventParam) = _importEuler(userAccount, sourceId, targetId, inputData, enterMarket); - } - - function _importEuler( - address userAccount, - uint256 sourceId, - uint256 targetId, - ImportInputData memory inputData, - bool[] memory enterMarket - ) - internal - returns (string memory _eventName, bytes memory _eventParam) - { - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); - require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); - require(enterMarket.length == inputData.supplyTokens.length, "lengths-not-same"); - - address _sourceAccount = getSubAccountAddress(userAccount, sourceId); - address _targetAccount = getSubAccountAddress(address(this), targetId); - - ImportData memory data; - - data = getBorrowAmounts(_sourceAccount, inputData, data); - data = getSupplyAmounts(_targetAccount, inputData, data); - - eulerExec.deferLiquidityCheck(_sourceAccount, abi.encode(data, enterMarket, _sourceAccount, _targetAccount, targetId)); - - _eventName = "LogEulerImport(address,uint256,uint256,address[],address[],uint256[],uint256[],bool[])"; - _eventParam = abi.encode( - userAccount, - sourceId, - targetId, - inputData.supplyTokens, - inputData.borrowTokens, - data.supplyAmts, - data.borrowAmts, - enterMarket - ); - } - - function onDeferredLiquidityCheck(bytes memory encodedData) external { - ( - ImportData memory data, - bool[] memory enterMarket, - address _sourceAccount, - address _targetAccount, - uint targetId - ) = abi.decode(encodedData, (ImportData, bool[], address, address, uint)); - - _TransferEtokens( - data._supplyTokens.length, - data.eTokens, - data.supplyAmts, - data._supplyTokens, - enterMarket, - _sourceAccount, - _targetAccount, - targetId - ); - - _TransferDtokens( - data._borrowTokens.length, - data.dTokens, - data.borrowAmts, - data._borrowTokens, - _sourceAccount, - _targetAccount - ); - } -} - -contract ConnectV2EulerImport is EulerImport { - string public constant name = "Euler-import-v1.0"; -} diff --git a/contracts/mainnet/connectors/euler/euler-import/events.sol b/contracts/mainnet/connectors/euler/euler-import/events.sol new file mode 100644 index 00000000..f6f42b21 --- /dev/null +++ b/contracts/mainnet/connectors/euler/euler-import/events.sol @@ -0,0 +1,15 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +contract Events { + + event LogEulerImport ( + address user, + uint sourceId, + uint targetId, + address[] supplyTokens, + address[] borrowTokens, + bool[] enterMarket + ) +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol similarity index 69% rename from contracts/mainnet/connectors/euler-import/helpers.sol rename to contracts/mainnet/connectors/euler/euler-import/helpers.sol index 19de35af..67352f28 100644 --- a/contracts/mainnet/connectors/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -1,8 +1,8 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; -import { TokenInterface, AccountInterface } from "../../common/interfaces.sol"; -import { Basic } from "../../common/basic.sol"; +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import { Basic } from "../../../common/basic.sol"; import "./interface.sol"; contract EulerHelpers is Basic { @@ -36,6 +36,7 @@ contract EulerHelpers is Basic { struct ImportInputData { address[] supplyTokens; address[] borrowTokens; + bool[] enterMarket; } struct ImportData { @@ -48,7 +49,7 @@ contract EulerHelpers is Basic { } function getSupplyAmounts( - address userAccount, + address userAccount,//user's EOA sub-account address ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { @@ -72,7 +73,7 @@ contract EulerHelpers is Basic { : inputData.supplyTokens[i]; data._supplyTokens[i] = _token; data.eTokens[i] = EulerTokenInterface(markets.underlyingToEToken(_token)); - data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount); + data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount);//All 18 dec } return data; @@ -113,59 +114,4 @@ contract EulerHelpers is Basic { } return data; } - -//transfer and enter market - function _TransferEtokens( - uint256 _length, - EulerTokenInterface[] memory etokenContracts, - uint256[] memory amts, - address[] memory tokens, - bool[] memory enterMarket, - address userAccountFrom, - address userAccountTo, - uint256 targetId - ) internal { - for (uint256 i = 0; i < _length; i++) { - if (amts[i] > 0) { - uint256 _amt = amts[i]; - require( - etokenContracts[i].transferFrom( - userAccountFrom, - userAccountTo, - _amt - ), - "allowance?"//change - ); - - if (enterMarket[i]) { - markets.enterMarket(targetId, tokens[i]); - } else { - markets.exitMarket(targetId, tokens[i]); - } - } - } - } - - function _TransferDtokens( - uint256 _length, - EulerTokenInterface[] memory dtokenContracts, - uint256[] memory amts, - address[] memory tokens, - address eoaIdFrom, - address dsaIdTo - ) internal { - for (uint256 i = 0; i < _length; i++) { - if (amts[i] > 0) { - uint256 _amt = amts[i]; - require( - dtokenContracts[i].transferFrom( - eoaIdFrom, - dsaIdTo, - _amt - ), - "debt-transfer-failed?" - ); - } - } - } } diff --git a/contracts/mainnet/connectors/euler-import/interface.sol b/contracts/mainnet/connectors/euler/euler-import/interface.sol similarity index 92% rename from contracts/mainnet/connectors/euler-import/interface.sol rename to contracts/mainnet/connectors/euler/euler-import/interface.sol index a62a860b..a7e55f3c 100644 --- a/contracts/mainnet/connectors/euler-import/interface.sol +++ b/contracts/mainnet/connectors/euler/euler-import/interface.sol @@ -49,7 +49,7 @@ interface IEulerExecute { bytes result; } - function batchDispatch(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) external returns (EulerBatchItemResponse[] memory); + function batchDispatch(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) external; function deferLiquidityCheck(address account, bytes memory data) external; -} \ No newline at end of file +} diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol new file mode 100644 index 00000000..7c55b78f --- /dev/null +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -0,0 +1,150 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; +import "./helpers.sol"; +import "./interface.sol"; +import "./events.sol"; + +contract EulerImport is EulerHelpers { + + /** + * @dev Import Euler position . + * @notice Import EOA's Euler position to DSA's Euler position + * @param userAccount The address of the EOA from which position will be imported + * @param sourceId sub-account id of EOA from which the funds will be transferred + * @param targetId sub-account id of DSA to which the funds will be transferred + * @param inputData The struct containing all the neccessary input data + */ + function importEuler( + address userAccount, + uint256 sourceId, + uint256 targetId, + ImportInputData memory inputData + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (_eventName, _eventParam) = _importEuler(userAccount, sourceId, targetId, inputData); + } + + struct importHelper { + uint enterMarketLength; + uint supplylength; + uint borrowlength; + uint totalLength; + } + + /** + * @dev Import Euler position . + * @notice Import EOA's Euler position to DSA's Euler position + * @param userAccount The address of the EOA from which position will be imported + * @param sourceId sub-account id of EOA from which the funds will be transferred + * @param targetId sub-account id of DSA to which the funds will be transferred + * @param inputData The struct containing all the neccessary input data + */ + function _importEuler( + address userAccount, + uint256 sourceId, + uint256 targetId, + ImportInputData memory inputData + ) + internal + returns (string memory _eventName, bytes memory _eventParam) + { + + importHelper memory helper; + + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); + + ImportData memory data; + + helper.enterMarketLength = inputData.enterMarket.length; + + require(helper.enterMarketLength == inputData.supplyTokens.length, "lengths-not-same"); + + address _sourceAccount = getSubAccountAddress(userAccount, sourceId); + address _targetAccount = getSubAccountAddress(address(this), targetId); + + data = getBorrowAmounts(_sourceAccount, inputData, data); + + // In 18 dec + data = getSupplyAmounts(_sourceAccount, inputData, data); + + helper.supplylength = data._supplyTokens.length; + helper.borrowlength = data._borrowTokens.length; + uint count = 0; + + for(uint i = 0; i < helper.enterMarketLength; i++) { + count = inputData.enterMarket[i] ? count++ : count; + } + + helper.totalLength = count + helper.supplylength + helper.borrowlength; + + IEulerExecute.EulerBatchItem[] memory items = new IEulerExecute.EulerBatchItem[](helper.totalLength); + + uint k = 0; + + for(uint i = 0; i < helper.supplylength; i++) { + + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(data.eTokens[i]), + data: abi.encodeWithSignature( + "transferFrom(address,address,uint256)", + _sourceAccount, _targetAccount, data.supplyAmts[i] + ) + }); + k++; + + if (inputData.enterMarket[i]) { + + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(markets), + data: abi.encodeWithSignature( + "enterMarket(uint256,address)", + targetId, data._supplyTokens[i] + ) + }); + k++; + } + } + + for(uint j = 0; j < helper.borrowlength; j++) { + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(data.dTokens[j]), + data: abi.encodeWithSignature( + "transferFrom(address,address,uint256)", + _sourceAccount, _targetAccount, data.borrowAmts[j] + ) + }); + k++; + } + + address[] memory deferLiquidityChecks = new address[](2); + deferLiquidityChecks[0] = _sourceAccount; + deferLiquidityChecks[1] = _targetAccount; + + eulerExec.batchDispatch(items, deferLiquidityChecks); + + _eventName = "LogEulerImport(address,uint,uint,address[],address[],bool[])"; + _eventParam = abi.encode( + userAccount, + sourceId, + targetId, + inputData.supplyTokens, + inputData.borrowTokens, + inputData.enterMarket + ); + } +} + +contract ConnectV2EulerImport is EulerImport { + string public constant name = "Euler-import-v1.0"; +} From eab97baeffdad7e6cb998051a24e2094945708ea Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 25 Aug 2022 05:27:24 +0530 Subject: [PATCH 08/24] updated testcases --- .../mainnet/euler-import/euler-import.test.ts | 153 +++++++++++++----- 1 file changed, 111 insertions(+), 42 deletions(-) diff --git a/test/mainnet/euler-import/euler-import.test.ts b/test/mainnet/euler-import/euler-import.test.ts index fd3b10b1..bf795d23 100644 --- a/test/mainnet/euler-import/euler-import.test.ts +++ b/test/mainnet/euler-import/euler-import.test.ts @@ -5,7 +5,7 @@ import { addresses } from "../../../scripts/tests/mainnet/addresses"; import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; -import { ConnectV2EulerImport__factory, ConnectV2Euler__factory, IERC20__factory } from "../../../typechain"; +import { ConnectV2EulerImport__factory, IERC20__factory } from "../../../typechain"; import { parseEther, parseUnits } from "@ethersproject/units"; import { encodeSpells } from "../../../scripts/tests/encodeSpells"; const { ethers } = hre; @@ -21,33 +21,36 @@ const ACC_WETH = '0x05547D4e1A2191B91510Ea7fA8555a2788C70030' const Weth = parseUnits('50', 18) const token_weth = new ethers.Contract( - WETH, - [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}], - ethers.provider, - ) + WETH, + [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}], + ethers.provider, +) - const token_dai = new ethers.Contract( - DAI, - [{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}], - ethers.provider, - ) +const token_dai = new ethers.Contract( + DAI, + [{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}], + ethers.provider, +) - const eTokensABI = [ - "function approve(address, uint256) public", - "function balanceOf(address account) public view returns (uint256)", - "function allowance(address, address) public returns (uint256)", - "function deposit(uint256,uint256) public", +const eTokensABI = [ + "function approve(address, uint256) public", + "function balanceOf(address account) public view returns (uint256)", + "function allowance(address, address) public returns (uint256)", + "function deposit(uint256,uint256) public", + "function balanceOfUnderlying(address) public view returns (uint256)", + "function mint(uint256,uint256) public", + "function approveSubAccount(uint256, address, uint256) public" ]; const dTokensABI = [ - "function balanceOf(address account) public view returns (uint256)", - "function borrow(uint256,uint256) public" + "function balanceOf(address account) public view returns (uint256)", + "function borrow(uint256,uint256) public" ]; const marketsABI = [ - "function enterMarket(uint256,address) public", - "function underlyingToEToken(address) public view returns (address)", + "function enterMarket(uint256,address) public", + "function underlyingToEToken(address) public view returns (address)", "function underlyingToDToken(address) public view returns (address)" ] @@ -70,6 +73,7 @@ describe("Euler", function () { let dsaWallet0: any; let instaConnectorsV2: Contract; let masterSigner: Signer; + let walletAddr: any; before(async () => { await hre.network.provider.request({ @@ -79,7 +83,7 @@ describe("Euler", function () { forking: { // @ts-ignore jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 15178000, + blockNumber: 15179000, }, }, ], @@ -114,6 +118,7 @@ describe("Euler", function () { connectors: instaConnectorsV2, }); console.log("Connector address", connector.address); + walletAddr = (await wallet0.getAddress()).toString() }); it("should have contracts deployed", async () => { @@ -138,21 +143,23 @@ describe("Euler", function () { ); }); - describe("Create Euler position", async () => { + describe("Create Euler position in SUBACCOUNT 0", async () => { it("Should create Euler position of WETH(collateral) and DAI(debt)", async () => { // approve WETH to euler await token_weth.connect(wallet0).approve(euler_mainnet, Weth); console.log("Approved WETH"); - //deposit WETH in euler + // deposit WETH in euler await eWethContract.connect(wallet0).deposit("0", parseUnits('2', 18));//todo: check balance console.log("Supplied WETH on Euler"); + console.log("eWETH balance underlying: ", await eWethContract.connect(wallet0).balanceOfUnderlying(wallet0.getAddress())) - // enter WETH market + + // enter WETH market await marketsContract.connect(wallet0).enterMarket("0", WETH); console.log("Entered market for weth"); - //borrow DAI from Euler + // borrow DAI from Euler await dDaiContract.connect(wallet0).borrow("0", Dai); console.log("Borrowed DAI from Euler"); }); @@ -162,27 +169,89 @@ describe("Euler", function () { new BigNumber(50).multipliedBy(1e18).toString() ); }); - }); + }); + + describe("Create Euler position in SUBACCOUNT 1", async () => { + let sub1addr = ethers.BigNumber.from(walletAddr).xor(1).toHexString() + + it("Should create Euler self-position of WETH(collateral) and WETH(debt)", async () => { + // approve WETH to euler + await token_weth.connect(wallet0).approve(euler_mainnet, Weth); + console.log("Approved WETH"); + + // deposit WETH in euler + await eWethContract.connect(wallet0).deposit("1", parseUnits('2', 18));//todo: check balance + console.log("Supplied WETH on Euler"); + + // enter WETH market + await marketsContract.connect(wallet0).enterMarket("1", WETH); + console.log("Entered market for weth"); + + // mint WETH from Euler + await eWethContract.connect(wallet0).mint("1", parseUnits('1', 18)); + console.log("Minted WETH from Euler"); + console.log("eWETH balance underlying: ", await eWethContract.connect(wallet0).balanceOfUnderlying(sub1addr)) + }); + + it("Should check created position of user", async () => { + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(sub1addr)).to.be.gte(parseEther("3")); + }); + }); describe("Euler position migration", async () => { - it("Should migrate euler position", async () => { - const spells = [ - { - connector: "EULER-IMPORT-TEST-A", - method: "importEuler", - args: [ - (await wallet0.getAddress()).toString(), - "0", - "0", - [[WETH], [DAI]], - ["true"] - ] - }, - ]; - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.getAddress()); - const receipt = await tx.wait(); - }); + it("Approve sub-account0 eTokens for import to DSA sub-account 0", async () => { + let balance = await eWethContract.connect(wallet0).balanceOf(walletAddr) + await eWethContract.connect(wallet0).approve(dsaWallet0.address, balance); + }); + + it("Approve sub-account1 eTokens for import to DSA sub-account 2", async () => { + let balance = await eWethContract.connect(wallet0).balanceOf(ethers.BigNumber.from(walletAddr).xor(1).toHexString()) + await eWethContract.connect(wallet0).approveSubAccount("1", dsaWallet0.address, balance); + }); + + it("Should migrate euler position of sub-account 0", async () => { + console.log("walletAddr: ", walletAddr) + const spells = [ + { + connector: "EULER-IMPORT-TEST-A", + method: "importEuler", + args: [ + walletAddr, + "0", + "0", + [[WETH],[DAI],["true"]] + ] + }, + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.getAddress()); + const receipt = await tx.wait(); + }); + + it("Should check migration", async () => { + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(dsaWallet0.address)).to.be.gte(parseEther("2")); + }); + + it("Should migrate euler position of sub-account 1", async () => { + const spells = [ + { + connector: "EULER-IMPORT-TEST-A", + method: "importEuler", + args: [ + walletAddr, + "1", + "2", + [[WETH],[WETH],["true"]] + ] + }, + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.getAddress()); + const receipt = await tx.wait(); + }); + + it("Should check migration", async () => { + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(ethers.BigNumber.from(dsaWallet0.address).xor(2).toHexString())).to.be.gte(parseEther("3")); + }); }) }); }) \ No newline at end of file From da5716c0f31528e93b3d0201c399c1bdf57476ed Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 25 Aug 2022 05:37:37 +0530 Subject: [PATCH 09/24] minor fix --- contracts/mainnet/connectors/euler/euler-import/events.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/events.sol b/contracts/mainnet/connectors/euler/euler-import/events.sol index f6f42b21..4f7e6545 100644 --- a/contracts/mainnet/connectors/euler/euler-import/events.sol +++ b/contracts/mainnet/connectors/euler/euler-import/events.sol @@ -11,5 +11,5 @@ contract Events { address[] supplyTokens, address[] borrowTokens, bool[] enterMarket - ) + ); } \ No newline at end of file From cc526d5899ac2d1eb04644197021c70ff526a003 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 25 Aug 2022 17:40:58 +0530 Subject: [PATCH 10/24] minor updates + lint --- .../connectors/euler/euler-import/events.sol | 4 +- .../connectors/euler/euler-import/helpers.sol | 56 +++-- .../connectors/euler/euler-import/main.sol | 215 +++++++++--------- 3 files changed, 146 insertions(+), 129 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/events.sol b/contracts/mainnet/connectors/euler/euler-import/events.sol index 4f7e6545..3770a420 100644 --- a/contracts/mainnet/connectors/euler/euler-import/events.sol +++ b/contracts/mainnet/connectors/euler/euler-import/events.sol @@ -9,7 +9,9 @@ contract Events { uint sourceId, uint targetId, address[] supplyTokens, + uint256[] supplyAmounts, address[] borrowTokens, + uint256[] borrowAmounts, bool[] enterMarket ); -} \ No newline at end of file +} diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index 67352f28..2d9fc3a2 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -34,44 +34,52 @@ contract EulerHelpers is Basic { } struct ImportInputData { - address[] supplyTokens; - address[] borrowTokens; - bool[] enterMarket; + address[] _supplyTokens; + address[] _borrowTokens; + bool[] _enterMarket; } struct ImportData { - address[] _supplyTokens; - address[] _borrowTokens; + address[] supplyTokens; + address[] borrowTokens; EulerTokenInterface[] eTokens; EulerTokenInterface[] dTokens; uint256[] supplyAmts; uint256[] borrowAmts; } + struct ImportHelper { + uint256 supplylength; + uint256 borrowlength; + uint256 totalExecutions; + address sourceAccount; + address targetAccount; + } + function getSupplyAmounts( - address userAccount,//user's EOA sub-account address + address userAccount,// user's EOA sub-account address ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { - data.supplyAmts = new uint256[](inputData.supplyTokens.length); - data._supplyTokens = new address[](inputData.supplyTokens.length); - data.eTokens = new EulerTokenInterface[](inputData.supplyTokens.length); + data.supplyAmts = new uint256[](inputData._supplyTokens.length); + data.supplyTokens = new address[](inputData._supplyTokens.length); + data.eTokens = new EulerTokenInterface[](inputData._supplyTokens.length); - for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { - for (uint256 j = i; j < inputData.supplyTokens.length; j++) { + for (uint256 i = 0; i < inputData._supplyTokens.length; i++) { + for (uint256 j = i; j < inputData._supplyTokens.length; j++) { if (j != i) { require( - inputData.supplyTokens[i] != inputData.supplyTokens[j], + inputData._supplyTokens[i] != inputData._supplyTokens[j], "token-repeated" ); } } } - for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { - address _token = inputData.supplyTokens[i] == ethAddr + for (uint256 i = 0; i < inputData._supplyTokens.length; i++) { + address _token = inputData._supplyTokens[i] == ethAddr ? wethAddr - : inputData.supplyTokens[i]; - data._supplyTokens[i] = _token; + : inputData._supplyTokens[i]; + data.supplyTokens[i] = _token; data.eTokens[i] = EulerTokenInterface(markets.underlyingToEToken(_token)); data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount);//All 18 dec } @@ -80,22 +88,22 @@ contract EulerHelpers is Basic { } function getBorrowAmounts( - address userAccount,//user's EOA sub-account address + address userAccount,// user's EOA sub-account address ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { - uint _borrowTokensLength = inputData.borrowTokens.length; + uint _borrowTokensLength = inputData._borrowTokens.length; if (_borrowTokensLength > 0) { - data._borrowTokens = new address[](_borrowTokensLength); + data.borrowTokens = new address[](_borrowTokensLength); data.dTokens = new EulerTokenInterface[](_borrowTokensLength); data.borrowAmts = new uint256[](_borrowTokensLength); for (uint256 i = 0; i < _borrowTokensLength; i++) { for (uint256 j = i; j < _borrowTokensLength; j++) { if (j != i) { require( - inputData.borrowTokens[i] != - inputData.borrowTokens[j], + inputData._borrowTokens[i] != + inputData._borrowTokens[j], "token-repeated" ); } @@ -103,11 +111,11 @@ contract EulerHelpers is Basic { } for (uint256 i = 0; i < _borrowTokensLength; i++) { - address _token = inputData.borrowTokens[i] == ethAddr + address _token = inputData._borrowTokens[i] == ethAddr ? wethAddr - : inputData.borrowTokens[i]; + : inputData._borrowTokens[i]; - data._borrowTokens[i] = _token; + data.borrowTokens[i] = _token; data.dTokens[i] = EulerTokenInterface(markets.underlyingToDToken(_token)); data.borrowAmts[i] = data.dTokens[i].balanceOf(userAccount); } diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 7c55b78f..c8ea0237 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -6,143 +6,150 @@ import "./interface.sol"; import "./events.sol"; contract EulerImport is EulerHelpers { - - /** + /** * @dev Import Euler position . * @notice Import EOA's Euler position to DSA's Euler position - * @param userAccount The address of the EOA from which position will be imported - * @param sourceId sub-account id of EOA from which the funds will be transferred - * @param targetId sub-account id of DSA to which the funds will be transferred - * @param inputData The struct containing all the neccessary input data + * @param userAccount EOA address + * @param sourceId Sub-account id of "EOA" from which the funds will be transferred + * @param targetId Sub-account id of "DSA" to which the funds will be transferred + * @param inputData The struct containing all the neccessary input data */ - function importEuler( - address userAccount, - uint256 sourceId, - uint256 targetId, - ImportInputData memory inputData - ) + function importEuler( + address userAccount, + uint256 sourceId, + uint256 targetId, + ImportInputData memory inputData + ) external payable - returns (string memory _eventName, bytes memory _eventParam) + returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importEuler(userAccount, sourceId, targetId, inputData); + (_eventName, _eventParam) = _importEuler( + userAccount, + sourceId, + targetId, + inputData + ); } - struct importHelper { - uint enterMarketLength; - uint supplylength; - uint borrowlength; - uint totalLength; - } - - /** + /** * @dev Import Euler position . * @notice Import EOA's Euler position to DSA's Euler position - * @param userAccount The address of the EOA from which position will be imported - * @param sourceId sub-account id of EOA from which the funds will be transferred - * @param targetId sub-account id of DSA to which the funds will be transferred - * @param inputData The struct containing all the neccessary input data + * @param userAccount EOA address + * @param sourceId Sub-account id of "EOA" from which the funds will be transferred + * @param targetId Sub-account id of "DSA" to which the funds will be transferred + * @param inputData The struct containing all the neccessary input data */ - function _importEuler( - address userAccount, - uint256 sourceId, - uint256 targetId, - ImportInputData memory inputData - ) - internal - returns (string memory _eventName, bytes memory _eventParam) - { + function _importEuler( + address userAccount, + uint256 sourceId, + uint256 targetId, + ImportInputData memory inputData + ) + internal + returns (string memory _eventName, bytes memory _eventParam) + { - importHelper memory helper; - - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); - require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); + require(inputData._supplyTokens.length > 0, "0-length-not-allowed"); + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + require( + inputData._enterMarket.length == inputData._supplyTokens.length, + "lengths-not-same" + ); ImportData memory data; + ImportHelper memory helper; - helper.enterMarketLength = inputData.enterMarket.length; + helper.sourceAccount = getSubAccountAddress(userAccount, sourceId); + helper.targetAccount = getSubAccountAddress(address(this), targetId); - require(helper.enterMarketLength == inputData.supplyTokens.length, "lengths-not-same"); + // BorrowAmts will be in underlying token decimals + data = getBorrowAmounts(helper.sourceAccount, inputData, data); - address _sourceAccount = getSubAccountAddress(userAccount, sourceId); - address _targetAccount = getSubAccountAddress(address(this), targetId); + // SupplyAmts will be in 18 decimals + data = getSupplyAmounts(helper.sourceAccount, inputData, data); - data = getBorrowAmounts(_sourceAccount, inputData, data); + helper.supplylength = data.supplyTokens.length; + helper.borrowlength = data.borrowTokens.length; + uint16 enterMarkets = 0; - // In 18 dec - data = getSupplyAmounts(_sourceAccount, inputData, data); + for (uint16 i = 0; i < inputData._enterMarket.length; i++) { + if (inputData._enterMarket[i]) { + ++enterMarkets; + } + } - helper.supplylength = data._supplyTokens.length; - helper.borrowlength = data._borrowTokens.length; - uint count = 0; + helper.totalExecutions = helper.supplylength + enterMarkets + helper.borrowlength; - for(uint i = 0; i < helper.enterMarketLength; i++) { - count = inputData.enterMarket[i] ? count++ : count; - } + IEulerExecute.EulerBatchItem[] + memory items = new IEulerExecute.EulerBatchItem[]( + helper.totalExecutions + ); - helper.totalLength = count + helper.supplylength + helper.borrowlength; + uint16 k = 0; - IEulerExecute.EulerBatchItem[] memory items = new IEulerExecute.EulerBatchItem[](helper.totalLength); + for (uint16 i = 0; i < helper.supplylength; i++) { + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(data.eTokens[i]), + data: abi.encodeWithSignature( + "transferFrom(address,address,uint256)", + helper.sourceAccount, + helper.targetAccount, + data.supplyAmts[i] + ) + }); + k++; - uint k = 0; + if (inputData._enterMarket[i]) { + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(markets), + data: abi.encodeWithSignature( + "enterMarket(uint256,address)", + targetId, + data.supplyTokens[i] + ) + }); + k++; + } + } - for(uint i = 0; i < helper.supplylength; i++) { + for (uint16 j = 0; j < helper.borrowlength; j++) { + items[k] = IEulerExecute.EulerBatchItem({ + allowError: false, + proxyAddr: address(data.dTokens[j]), + data: abi.encodeWithSignature( + "transferFrom(address,address,uint256)", + helper.sourceAccount, + helper.targetAccount, + data.borrowAmts[j] + ) + }); + k++; + } - items[k] = IEulerExecute.EulerBatchItem({ - allowError: false, - proxyAddr: address(data.eTokens[i]), - data: abi.encodeWithSignature( - "transferFrom(address,address,uint256)", - _sourceAccount, _targetAccount, data.supplyAmts[i] - ) - }); - k++; + address[] memory deferLiquidityChecks = new address[](2); + deferLiquidityChecks[0] = helper.sourceAccount; + deferLiquidityChecks[1] = helper.targetAccount; - if (inputData.enterMarket[i]) { + eulerExec.batchDispatch(items, deferLiquidityChecks); - items[k] = IEulerExecute.EulerBatchItem({ - allowError: false, - proxyAddr: address(markets), - data: abi.encodeWithSignature( - "enterMarket(uint256,address)", - targetId, data._supplyTokens[i] - ) - }); - k++; - } - } - - for(uint j = 0; j < helper.borrowlength; j++) { - items[k] = IEulerExecute.EulerBatchItem({ - allowError: false, - proxyAddr: address(data.dTokens[j]), - data: abi.encodeWithSignature( - "transferFrom(address,address,uint256)", - _sourceAccount, _targetAccount, data.borrowAmts[j] - ) - }); - k++; - } - - address[] memory deferLiquidityChecks = new address[](2); - deferLiquidityChecks[0] = _sourceAccount; - deferLiquidityChecks[1] = _targetAccount; - - eulerExec.batchDispatch(items, deferLiquidityChecks); - - _eventName = "LogEulerImport(address,uint,uint,address[],address[],bool[])"; + _eventName = "LogEulerImport(address,uint,uint,address[],address[],bool[])"; _eventParam = abi.encode( userAccount, sourceId, targetId, - inputData.supplyTokens, - inputData.borrowTokens, - inputData.enterMarket + inputData._supplyTokens, + data.supplyAmts, + inputData._borrowTokens, + data.borrowAmts, + inputData._enterMarket ); - } + } } contract ConnectV2EulerImport is EulerImport { From 4bedea9aea556aa830427e74fd3d0d47b992dae5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 25 Aug 2022 17:41:42 +0530 Subject: [PATCH 11/24] testcases updated --- .../mainnet/euler-import/euler-import.test.ts | 93 +++++++++++-------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/test/mainnet/euler-import/euler-import.test.ts b/test/mainnet/euler-import/euler-import.test.ts index bf795d23..b50500f1 100644 --- a/test/mainnet/euler-import/euler-import.test.ts +++ b/test/mainnet/euler-import/euler-import.test.ts @@ -11,28 +11,30 @@ import { encodeSpells } from "../../../scripts/tests/encodeSpells"; const { ethers } = hre; import type { Signer, Contract } from "ethers"; import { BigNumber } from "bignumber.js"; +import { Address } from "@project-serum/anchor"; const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' -const ACC_DAI = '0xcd6Eb888e76450eF584E8B51bB73c76ffBa21FF2' const Dai = parseUnits('50', 18) const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' const ACC_WETH = '0x05547D4e1A2191B91510Ea7fA8555a2788C70030' const Weth = parseUnits('50', 18) +const ETH = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' + const token_weth = new ethers.Contract( WETH, [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}], + // IERC20__factory.abi, ethers.provider, ) const token_dai = new ethers.Contract( DAI, - [{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}], + IERC20__factory.abi, ethers.provider, ) - const eTokensABI = [ "function approve(address, uint256) public", "function balanceOf(address account) public view returns (uint256)", @@ -54,9 +56,12 @@ const marketsABI = [ "function underlyingToDToken(address) public view returns (address)" ] -const eWethAddress = "0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D"; +const eWethAddress = '0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D'; const eWethContract = new ethers.Contract(eWethAddress, eTokensABI); +const dWethAddress = '0x62e28f054efc24b26A794F5C1249B6349454352C' +const dWethContract = new ethers.Contract(dWethAddress, dTokensABI); + const dDaiAddress = '0x6085Bc95F506c326DCBCD7A6dd6c79FBc18d4686'; const dDaiContract = new ethers.Contract(dDaiAddress, dTokensABI); @@ -73,7 +78,9 @@ describe("Euler", function () { let dsaWallet0: any; let instaConnectorsV2: Contract; let masterSigner: Signer; - let walletAddr: any; + let walletAddr: Address; + let subAcc1: Address; + let subAcc2DSA: Address; before(async () => { await hre.network.provider.request({ @@ -83,28 +90,28 @@ describe("Euler", function () { forking: { // @ts-ignore jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 15179000, + blockNumber: 15379000, }, }, ], }); [wallet0, wallet1] = await ethers.getSigners(); - await hre.network.provider.send("hardhat_setBalance", [ACC_WETH, ethers.utils.parseEther("10").toHexString()]); + await hre.network.provider.send("hardhat_setBalance", [ACC_WETH, ethers.utils.parseEther("10").toHexString()]); - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ACC_WETH] - }); + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_WETH] + }); - const signer_weth = await ethers.getSigner(ACC_WETH) - await token_weth.connect(signer_weth).transfer(wallet0.getAddress(), ethers.utils.parseEther("8")); - console.log("weth transferred to wallet0"); + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(wallet0.getAddress(), ethers.utils.parseEther("8")); + console.log("WETH transferred to wallet0"); - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_WETH], - }) + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) masterSigner = await getMasterSigner(); instaConnectorsV2 = await ethers.getContractAt( @@ -119,6 +126,9 @@ describe("Euler", function () { }); console.log("Connector address", connector.address); walletAddr = (await wallet0.getAddress()).toString() + console.log("walletAddr: ", walletAddr) + subAcc1 = ethers.BigNumber.from(walletAddr).xor(1).toHexString() + console.log("subAcc1: ", subAcc1) }); it("should have contracts deployed", async () => { @@ -131,6 +141,9 @@ describe("Euler", function () { it("Should build DSA v2", async function () { dsaWallet0 = await buildDSAv2(wallet0.getAddress()); expect(!!dsaWallet0.address).to.be.true; + + subAcc2DSA = ethers.BigNumber.from(dsaWallet0.address).xor(2).toHexString() + console.log("subAcc2DSA: ", subAcc2DSA) }); it("Deposit ETH into DSA wallet", async function () { @@ -150,14 +163,13 @@ describe("Euler", function () { console.log("Approved WETH"); // deposit WETH in euler - await eWethContract.connect(wallet0).deposit("0", parseUnits('2', 18));//todo: check balance + await eWethContract.connect(wallet0).deposit("0", parseEther("2")); + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(walletAddr)).to.be.gte(parseEther("1.9")); console.log("Supplied WETH on Euler"); - console.log("eWETH balance underlying: ", await eWethContract.connect(wallet0).balanceOfUnderlying(wallet0.getAddress())) - // enter WETH market await marketsContract.connect(wallet0).enterMarket("0", WETH); - console.log("Entered market for weth"); + console.log("Entered market for WETH"); // borrow DAI from Euler await dDaiContract.connect(wallet0).borrow("0", Dai); @@ -165,53 +177,50 @@ describe("Euler", function () { }); it("Should check created position of user", async () => { - expect(await token_dai.connect(wallet0).balanceOf(wallet0.getAddress())).to.be.gte( - new BigNumber(50).multipliedBy(1e18).toString() + expect(await token_dai.connect(wallet0).balanceOf(walletAddr)).to.be.gte( + parseUnits('50', 18) ); }); }); - describe("Create Euler position in SUBACCOUNT 1", async () => { - let sub1addr = ethers.BigNumber.from(walletAddr).xor(1).toHexString() - + describe("Create Euler self-position in SUBACCOUNT 1", async () => { it("Should create Euler self-position of WETH(collateral) and WETH(debt)", async () => { // approve WETH to euler await token_weth.connect(wallet0).approve(euler_mainnet, Weth); console.log("Approved WETH"); // deposit WETH in euler - await eWethContract.connect(wallet0).deposit("1", parseUnits('2', 18));//todo: check balance + await eWethContract.connect(wallet0).deposit("1", parseEther("2")); + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(subAcc1)).to.be.gte(parseEther("1.9")); console.log("Supplied WETH on Euler"); // enter WETH market await marketsContract.connect(wallet0).enterMarket("1", WETH); - console.log("Entered market for weth"); + console.log("Entered market for WETH"); // mint WETH from Euler - await eWethContract.connect(wallet0).mint("1", parseUnits('1', 18)); + await eWethContract.connect(wallet0).mint("1", parseEther("1")); + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(subAcc1)).to.be.gte(parseEther("2.9")); console.log("Minted WETH from Euler"); - console.log("eWETH balance underlying: ", await eWethContract.connect(wallet0).balanceOfUnderlying(sub1addr)) }); it("Should check created position of user", async () => { - expect(await eWethContract.connect(wallet0).balanceOfUnderlying(sub1addr)).to.be.gte(parseEther("3")); + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(subAcc1)).to.be.gte(parseEther("2.9")); }); }); describe("Euler position migration", async () => { - it("Approve sub-account0 eTokens for import to DSA sub-account 0", async () => { let balance = await eWethContract.connect(wallet0).balanceOf(walletAddr) await eWethContract.connect(wallet0).approve(dsaWallet0.address, balance); }); it("Approve sub-account1 eTokens for import to DSA sub-account 2", async () => { - let balance = await eWethContract.connect(wallet0).balanceOf(ethers.BigNumber.from(walletAddr).xor(1).toHexString()) + let balance = await eWethContract.connect(wallet0).balanceOf(subAcc1) await eWethContract.connect(wallet0).approveSubAccount("1", dsaWallet0.address, balance); }); - it("Should migrate euler position of sub-account 0", async () => { - console.log("walletAddr: ", walletAddr) + it("Should migrate euler position of sub-account 0 to DSA sub-account 0", async () => { const spells = [ { connector: "EULER-IMPORT-TEST-A", @@ -220,7 +229,7 @@ describe("Euler", function () { walletAddr, "0", "0", - [[WETH],[DAI],["true"]] + [[ETH],[DAI],["true"]] ] }, ]; @@ -230,9 +239,10 @@ describe("Euler", function () { it("Should check migration", async () => { expect(await eWethContract.connect(wallet0).balanceOfUnderlying(dsaWallet0.address)).to.be.gte(parseEther("2")); + expect(await dDaiContract.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(parseEther("50")); }); - it("Should migrate euler position of sub-account 1", async () => { + it("Should migrate euler position of sub-account 1 to DSA sub-account 2", async () => { const spells = [ { connector: "EULER-IMPORT-TEST-A", @@ -241,7 +251,7 @@ describe("Euler", function () { walletAddr, "1", "2", - [[WETH],[WETH],["true"]] + [[ETH],[ETH],["true"]] ] }, ]; @@ -250,8 +260,9 @@ describe("Euler", function () { }); it("Should check migration", async () => { - expect(await eWethContract.connect(wallet0).balanceOfUnderlying(ethers.BigNumber.from(dsaWallet0.address).xor(2).toHexString())).to.be.gte(parseEther("3")); + expect(await eWethContract.connect(wallet0).balanceOfUnderlying(subAcc2DSA)).to.be.gte(parseEther("3")); + expect(await dWethContract.connect(wallet0).balanceOf(subAcc2DSA)).to.be.gte(parseEther("1")); }); }) }); -}) \ No newline at end of file +}) From 14bbd57567854249f80fe8e23c28f24c0d349ade Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:08:07 +0530 Subject: [PATCH 12/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: Thrilok kumar --- contracts/mainnet/connectors/euler/euler-import/main.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index c8ea0237..f043476b 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -144,9 +144,9 @@ contract EulerImport is EulerHelpers { sourceId, targetId, inputData._supplyTokens, - data.supplyAmts, + data.supplyAmts, inputData._borrowTokens, - data.borrowAmts, + data.borrowAmts, inputData._enterMarket ); } From fed7297b605bf04d4f92d320589211a1d3148cac Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:09:54 +0530 Subject: [PATCH 13/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: Thrilok kumar --- contracts/mainnet/connectors/euler/euler-import/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index f043476b..1d9419fb 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -138,7 +138,7 @@ contract EulerImport is EulerHelpers { eulerExec.batchDispatch(items, deferLiquidityChecks); - _eventName = "LogEulerImport(address,uint,uint,address[],address[],bool[])"; + _eventName = "LogEulerImport(address,uint256,uint256,address[],uint256[],address[],uint256[],bool[])"; _eventParam = abi.encode( userAccount, sourceId, From 3c257867e34a568156e68af733f0b1586d852144 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:10:49 +0530 Subject: [PATCH 14/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: Thrilok kumar --- contracts/mainnet/connectors/euler/euler-import/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 1d9419fb..0efaf305 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -74,7 +74,7 @@ contract EulerImport is EulerHelpers { helper.supplylength = data.supplyTokens.length; helper.borrowlength = data.borrowTokens.length; - uint16 enterMarkets = 0; + uint16 enterMarketsLength = 0; for (uint16 i = 0; i < inputData._enterMarket.length; i++) { if (inputData._enterMarket[i]) { From 44fc1e812fdd3a70d9d0e3c5b85f56821937315d Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:12:08 +0530 Subject: [PATCH 15/24] Update contracts/mainnet/connectors/euler/euler-import/helpers.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- .../mainnet/connectors/euler/euler-import/helpers.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index 2d9fc3a2..accb531d 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -64,18 +64,16 @@ contract EulerHelpers is Basic { data.supplyAmts = new uint256[](inputData._supplyTokens.length); data.supplyTokens = new address[](inputData._supplyTokens.length); data.eTokens = new EulerTokenInterface[](inputData._supplyTokens.length); - - for (uint256 i = 0; i < inputData._supplyTokens.length; i++) { - for (uint256 j = i; j < inputData._supplyTokens.length; j++) { - if (j != i) { + uint256 length_ = inputData._supplyTokens.length; + for (uint256 i = 0; i < length_; i++) { + for (uint256 j = i + 1; j < length_; j++) { require( inputData._supplyTokens[i] != inputData._supplyTokens[j], "token-repeated" ); - } } } - for (uint256 i = 0; i < inputData._supplyTokens.length; i++) { + for (uint256 i = 0; i < length_; i++) { address _token = inputData._supplyTokens[i] == ethAddr ? wethAddr : inputData._supplyTokens[i]; From bd03d6e7098dd66a9c99bc29e5a60ac1333a3429 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:12:50 +0530 Subject: [PATCH 16/24] Update contracts/mainnet/connectors/euler/euler-import/helpers.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- contracts/mainnet/connectors/euler/euler-import/helpers.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index accb531d..34c15fdc 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -97,14 +97,12 @@ contract EulerHelpers is Basic { data.dTokens = new EulerTokenInterface[](_borrowTokensLength); data.borrowAmts = new uint256[](_borrowTokensLength); for (uint256 i = 0; i < _borrowTokensLength; i++) { - for (uint256 j = i; j < _borrowTokensLength; j++) { - if (j != i) { + for (uint256 j = i + 1; j < _borrowTokensLength; j++) { require( inputData._borrowTokens[i] != inputData._borrowTokens[j], "token-repeated" ); - } } } From ecb57503ee5d14bb6b5c624e43e2d532e084486b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 26 Aug 2022 15:36:30 +0530 Subject: [PATCH 17/24] minor edits + lint --- .../connectors/euler/euler-import/events.sol | 21 ++++--- .../connectors/euler/euler-import/helpers.sol | 60 ++++++++++--------- .../euler/euler-import/interface.sol | 9 +-- .../connectors/euler/euler-import/main.sol | 39 ++++++------ 4 files changed, 68 insertions(+), 61 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/events.sol b/contracts/mainnet/connectors/euler/euler-import/events.sol index 3770a420..8d7db584 100644 --- a/contracts/mainnet/connectors/euler/euler-import/events.sol +++ b/contracts/mainnet/connectors/euler/euler-import/events.sol @@ -3,15 +3,14 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; contract Events { - - event LogEulerImport ( - address user, - uint sourceId, - uint targetId, - address[] supplyTokens, - uint256[] supplyAmounts, - address[] borrowTokens, - uint256[] borrowAmounts, - bool[] enterMarket - ); + event LogEulerImport( + address user, + uint256 sourceId, + uint256 targetId, + address[] supplyTokens, + uint256[] supplyAmounts, + address[] borrowTokens, + uint256[] borrowAmounts, + bool[] enterMarket + ); } diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index 34c15fdc..97a89e03 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -6,23 +6,23 @@ import { Basic } from "../../../common/basic.sol"; import "./interface.sol"; contract EulerHelpers is Basic { - /** * @dev Euler's Market Module */ - IEulerMarkets internal constant markets = + IEulerMarkets internal constant markets = IEulerMarkets(0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3); /** * @dev Euler's Execution Module */ - IEulerExecute internal constant eulerExec = IEulerExecute(0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80); + IEulerExecute internal constant eulerExec = + IEulerExecute(0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80); /** * @dev Compute sub account address. * @notice Compute sub account address from sub-account id * @param primary primary address - * @param subAccountId sub-account id whose address needs to be computed + * @param subAccountId sub-account id whose address needs to be computed */ function getSubAccountAddress(address primary, uint256 subAccountId) public @@ -33,17 +33,17 @@ contract EulerHelpers is Basic { return address(uint160(primary) ^ uint160(subAccountId)); } - struct ImportInputData { + struct ImportInputData { address[] _supplyTokens; address[] _borrowTokens; bool[] _enterMarket; } - struct ImportData { + struct ImportData { address[] supplyTokens; address[] borrowTokens; EulerTokenInterface[] eTokens; - EulerTokenInterface[] dTokens; + EulerTokenInterface[] dTokens; uint256[] supplyAmts; uint256[] borrowAmts; } @@ -56,21 +56,23 @@ contract EulerHelpers is Basic { address targetAccount; } - function getSupplyAmounts( - address userAccount,// user's EOA sub-account address + function getSupplyAmounts( + address userAccount, // user's EOA sub-account address ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { data.supplyAmts = new uint256[](inputData._supplyTokens.length); data.supplyTokens = new address[](inputData._supplyTokens.length); - data.eTokens = new EulerTokenInterface[](inputData._supplyTokens.length); - uint256 length_ = inputData._supplyTokens.length; + data.eTokens = new EulerTokenInterface[]( + inputData._supplyTokens.length + ); + uint256 length_ = inputData._supplyTokens.length; for (uint256 i = 0; i < length_; i++) { for (uint256 j = i + 1; j < length_; j++) { - require( - inputData._supplyTokens[i] != inputData._supplyTokens[j], - "token-repeated" - ); + require( + inputData._supplyTokens[i] != inputData._supplyTokens[j], + "token-repeated" + ); } } for (uint256 i = 0; i < length_; i++) { @@ -78,19 +80,21 @@ contract EulerHelpers is Basic { ? wethAddr : inputData._supplyTokens[i]; data.supplyTokens[i] = _token; - data.eTokens[i] = EulerTokenInterface(markets.underlyingToEToken(_token)); - data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount);//All 18 dec + data.eTokens[i] = EulerTokenInterface( + markets.underlyingToEToken(_token) + ); + data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount); //All 18 dec } return data; } - function getBorrowAmounts( - address userAccount,// user's EOA sub-account address + function getBorrowAmounts( + address userAccount, // user's EOA sub-account address ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { - uint _borrowTokensLength = inputData._borrowTokens.length; + uint256 _borrowTokensLength = inputData._borrowTokens.length; if (_borrowTokensLength > 0) { data.borrowTokens = new address[](_borrowTokensLength); @@ -98,11 +102,11 @@ contract EulerHelpers is Basic { data.borrowAmts = new uint256[](_borrowTokensLength); for (uint256 i = 0; i < _borrowTokensLength; i++) { for (uint256 j = i + 1; j < _borrowTokensLength; j++) { - require( - inputData._borrowTokens[i] != - inputData._borrowTokens[j], - "token-repeated" - ); + require( + inputData._borrowTokens[i] != + inputData._borrowTokens[j], + "token-repeated" + ); } } @@ -112,8 +116,10 @@ contract EulerHelpers is Basic { : inputData._borrowTokens[i]; data.borrowTokens[i] = _token; - data.dTokens[i] = EulerTokenInterface(markets.underlyingToDToken(_token)); - data.borrowAmts[i] = data.dTokens[i].balanceOf(userAccount); + data.dTokens[i] = EulerTokenInterface( + markets.underlyingToDToken(_token) + ); + data.borrowAmts[i] = data.dTokens[i].balanceOf(userAccount); } } return data; diff --git a/contracts/mainnet/connectors/euler/euler-import/interface.sol b/contracts/mainnet/connectors/euler/euler-import/interface.sol index a7e55f3c..3cf7144f 100644 --- a/contracts/mainnet/connectors/euler/euler-import/interface.sol +++ b/contracts/mainnet/connectors/euler/euler-import/interface.sol @@ -3,7 +3,6 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; interface EulerTokenInterface { - function balanceOf(address _user) external view returns (uint256); function transferFrom( @@ -37,19 +36,21 @@ interface IEulerMarkets { } interface IEulerExecute { - struct EulerBatchItem { bool allowError; address proxyAddr; bytes data; } - + struct EulerBatchItemResponse { bool success; bytes result; } - function batchDispatch(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) external; + function batchDispatch( + EulerBatchItem[] calldata items, + address[] calldata deferLiquidityChecks + ) external; function deferLiquidityCheck(address account, bytes memory data) external; } diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 0efaf305..4022569e 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -24,6 +24,8 @@ contract EulerImport is EulerHelpers { payable returns (string memory _eventName, bytes memory _eventParam) { + require(sourceId < 256 && targetId < 256, "Id should be less than 256"); + (_eventName, _eventParam) = _importEuler( userAccount, sourceId, @@ -45,28 +47,24 @@ contract EulerImport is EulerHelpers { uint256 sourceId, uint256 targetId, ImportInputData memory inputData - ) - internal - returns (string memory _eventName, bytes memory _eventParam) - { + ) internal returns (string memory _eventName, bytes memory _eventParam) { + require(inputData._supplyTokens.length > 0, "0-length-not-allowed"); + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + require( + inputData._enterMarket.length == inputData._supplyTokens.length, + "lengths-not-same" + ); - require(inputData._supplyTokens.length > 0, "0-length-not-allowed"); - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); - require( - inputData._enterMarket.length == inputData._supplyTokens.length, - "lengths-not-same" - ); - - ImportData memory data; - ImportHelper memory helper; + ImportData memory data; + ImportHelper memory helper; helper.sourceAccount = getSubAccountAddress(userAccount, sourceId); helper.targetAccount = getSubAccountAddress(address(this), targetId); - // BorrowAmts will be in underlying token decimals + // BorrowAmts will be in underlying token decimals data = getBorrowAmounts(helper.sourceAccount, inputData, data); // SupplyAmts will be in 18 decimals @@ -78,11 +76,14 @@ contract EulerImport is EulerHelpers { for (uint16 i = 0; i < inputData._enterMarket.length; i++) { if (inputData._enterMarket[i]) { - ++enterMarkets; + ++enterMarketsLength; } } - helper.totalExecutions = helper.supplylength + enterMarkets + helper.borrowlength; + helper.totalExecutions = + helper.supplylength + + enterMarketsLength + + helper.borrowlength; IEulerExecute.EulerBatchItem[] memory items = new IEulerExecute.EulerBatchItem[]( From b3c4bad608c7aef48e45f2544d2213d6638fd508 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 22:29:54 +0530 Subject: [PATCH 18/24] Update contracts/mainnet/connectors/euler/euler-import/helpers.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- contracts/mainnet/connectors/euler/euler-import/helpers.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index 97a89e03..45a57d9c 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -94,9 +94,9 @@ contract EulerHelpers is Basic { ImportInputData memory inputData, ImportData memory data ) internal view returns (ImportData memory) { - uint256 _borrowTokensLength = inputData._borrowTokens.length; + uint256 borrowTokensLength_ = inputData._borrowTokens.length; - if (_borrowTokensLength > 0) { + if (borrowTokensLength_ > 0) { data.borrowTokens = new address[](_borrowTokensLength); data.dTokens = new EulerTokenInterface[](_borrowTokensLength); data.borrowAmts = new uint256[](_borrowTokensLength); From d2268093daaa245cc5f70f1e574828375124fb82 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 22:30:52 +0530 Subject: [PATCH 19/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- contracts/mainnet/connectors/euler/euler-import/main.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 4022569e..77d589f8 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -93,7 +93,7 @@ contract EulerImport is EulerHelpers { uint16 k = 0; for (uint16 i = 0; i < helper.supplylength; i++) { - items[k] = IEulerExecute.EulerBatchItem({ + items[k++] = IEulerExecute.EulerBatchItem({ allowError: false, proxyAddr: address(data.eTokens[i]), data: abi.encodeWithSignature( @@ -103,7 +103,6 @@ contract EulerImport is EulerHelpers { data.supplyAmts[i] ) }); - k++; if (inputData._enterMarket[i]) { items[k] = IEulerExecute.EulerBatchItem({ From d3582e37b97ea916859b25f17e493265630d6a41 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 22:41:20 +0530 Subject: [PATCH 20/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- contracts/mainnet/connectors/euler/euler-import/main.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 77d589f8..3c4144c7 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -105,7 +105,7 @@ contract EulerImport is EulerHelpers { }); if (inputData._enterMarket[i]) { - items[k] = IEulerExecute.EulerBatchItem({ + items[k++] = IEulerExecute.EulerBatchItem({ allowError: false, proxyAddr: address(markets), data: abi.encodeWithSignature( @@ -114,7 +114,6 @@ contract EulerImport is EulerHelpers { data.supplyTokens[i] ) }); - k++; } } From 0f360e399d7732ddb553e9a6c990d0b4f807bc19 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Fri, 26 Aug 2022 22:41:38 +0530 Subject: [PATCH 21/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol Co-authored-by: 0xPradyuman <63545809+pradyuman-verma@users.noreply.github.com> --- contracts/mainnet/connectors/euler/euler-import/main.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 3c4144c7..22b7ced6 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -118,7 +118,7 @@ contract EulerImport is EulerHelpers { } for (uint16 j = 0; j < helper.borrowlength; j++) { - items[k] = IEulerExecute.EulerBatchItem({ + items[k++] = IEulerExecute.EulerBatchItem({ allowError: false, proxyAddr: address(data.dTokens[j]), data: abi.encodeWithSignature( @@ -128,7 +128,6 @@ contract EulerImport is EulerHelpers { data.borrowAmts[j] ) }); - k++; } address[] memory deferLiquidityChecks = new address[](2); From 8e27bf770bc72da7e03ca179486cadd85caa4d82 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 26 Aug 2022 22:45:25 +0530 Subject: [PATCH 22/24] removed token-repeated loop --- .../connectors/euler/euler-import/helpers.sol | 32 +++++-------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/euler-import/helpers.sol index 45a57d9c..09f355b6 100644 --- a/contracts/mainnet/connectors/euler/euler-import/helpers.sol +++ b/contracts/mainnet/connectors/euler/euler-import/helpers.sol @@ -67,21 +67,14 @@ contract EulerHelpers is Basic { inputData._supplyTokens.length ); uint256 length_ = inputData._supplyTokens.length; + for (uint256 i = 0; i < length_; i++) { - for (uint256 j = i + 1; j < length_; j++) { - require( - inputData._supplyTokens[i] != inputData._supplyTokens[j], - "token-repeated" - ); - } - } - for (uint256 i = 0; i < length_; i++) { - address _token = inputData._supplyTokens[i] == ethAddr + address token_ = inputData._supplyTokens[i] == ethAddr ? wethAddr : inputData._supplyTokens[i]; - data.supplyTokens[i] = _token; + data.supplyTokens[i] = token_; data.eTokens[i] = EulerTokenInterface( - markets.underlyingToEToken(_token) + markets.underlyingToEToken(token_) ); data.supplyAmts[i] = data.eTokens[i].balanceOf(userAccount); //All 18 dec } @@ -97,20 +90,11 @@ contract EulerHelpers is Basic { uint256 borrowTokensLength_ = inputData._borrowTokens.length; if (borrowTokensLength_ > 0) { - data.borrowTokens = new address[](_borrowTokensLength); - data.dTokens = new EulerTokenInterface[](_borrowTokensLength); - data.borrowAmts = new uint256[](_borrowTokensLength); - for (uint256 i = 0; i < _borrowTokensLength; i++) { - for (uint256 j = i + 1; j < _borrowTokensLength; j++) { - require( - inputData._borrowTokens[i] != - inputData._borrowTokens[j], - "token-repeated" - ); - } - } + data.borrowTokens = new address[](borrowTokensLength_); + data.dTokens = new EulerTokenInterface[](borrowTokensLength_); + data.borrowAmts = new uint256[](borrowTokensLength_); - for (uint256 i = 0; i < _borrowTokensLength; i++) { + for (uint256 i = 0; i < borrowTokensLength_; i++) { address _token = inputData._borrowTokens[i] == ethAddr ? wethAddr : inputData._borrowTokens[i]; From 2b6649927550ecb1ced82aa6002bc215b8e4c3dd Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Sat, 27 Aug 2022 01:05:34 +0530 Subject: [PATCH 23/24] Update contracts/mainnet/connectors/euler/euler-import/main.sol --- contracts/mainnet/connectors/euler/euler-import/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/euler-import/main.sol index 22b7ced6..c6e1724b 100644 --- a/contracts/mainnet/connectors/euler/euler-import/main.sol +++ b/contracts/mainnet/connectors/euler/euler-import/main.sol @@ -151,5 +151,5 @@ contract EulerImport is EulerHelpers { } contract ConnectV2EulerImport is EulerImport { - string public constant name = "Euler-import-v1.0"; + string public constant name = "Euler-Import-v1.0"; } From d77c5baf199beac77c2771eb18d24be3190ca984 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 28 Aug 2022 00:23:54 +0530 Subject: [PATCH 24/24] Updated import folder name --- .../mainnet/connectors/euler/{euler-import => import}/events.sol | 0 .../mainnet/connectors/euler/{euler-import => import}/helpers.sol | 0 .../connectors/euler/{euler-import => import}/interface.sol | 0 .../mainnet/connectors/euler/{euler-import => import}/main.sol | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename contracts/mainnet/connectors/euler/{euler-import => import}/events.sol (100%) rename contracts/mainnet/connectors/euler/{euler-import => import}/helpers.sol (100%) rename contracts/mainnet/connectors/euler/{euler-import => import}/interface.sol (100%) rename contracts/mainnet/connectors/euler/{euler-import => import}/main.sol (100%) diff --git a/contracts/mainnet/connectors/euler/euler-import/events.sol b/contracts/mainnet/connectors/euler/import/events.sol similarity index 100% rename from contracts/mainnet/connectors/euler/euler-import/events.sol rename to contracts/mainnet/connectors/euler/import/events.sol diff --git a/contracts/mainnet/connectors/euler/euler-import/helpers.sol b/contracts/mainnet/connectors/euler/import/helpers.sol similarity index 100% rename from contracts/mainnet/connectors/euler/euler-import/helpers.sol rename to contracts/mainnet/connectors/euler/import/helpers.sol diff --git a/contracts/mainnet/connectors/euler/euler-import/interface.sol b/contracts/mainnet/connectors/euler/import/interface.sol similarity index 100% rename from contracts/mainnet/connectors/euler/euler-import/interface.sol rename to contracts/mainnet/connectors/euler/import/interface.sol diff --git a/contracts/mainnet/connectors/euler/euler-import/main.sol b/contracts/mainnet/connectors/euler/import/main.sol similarity index 100% rename from contracts/mainnet/connectors/euler/euler-import/main.sol rename to contracts/mainnet/connectors/euler/import/main.sol