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 {