diff --git a/contracts/optimism/common/interfaces.sol b/contracts/optimism/common/interfaces.sol index 03211b06..2239b473 100644 --- a/contracts/optimism/common/interfaces.sol +++ b/contracts/optimism/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; interface TokenInterface { function approve(address, uint256) external; @@ -22,4 +23,13 @@ interface AccountInterface { function enable(address) external; function disable(address) external; function isAuth(address) external view returns (bool); + function cast( + string[] calldata _targetNames, + bytes[] calldata _datas, + address _origin + ) external payable returns (bytes32[] memory responses); +} + +interface ListInterface { + function accountID(address) external returns (uint64); } diff --git a/contracts/optimism/connectors/aave/v3-import/events.sol b/contracts/optimism/connectors/aave/v3-import/events.sol index 2a1c4e23..6317bdba 100644 --- a/contracts/optimism/connectors/aave/v3-import/events.sol +++ b/contracts/optimism/connectors/aave/v3-import/events.sol @@ -5,7 +5,7 @@ pragma experimental ABIEncoderV2; contract Events { event LogAaveV3Import( address indexed user, - address[] ctokens, + address[] atokens, string[] supplyIds, string[] borrowIds, uint256[] flashLoanFees, @@ -14,7 +14,7 @@ contract Events { ); event LogAaveV3ImportWithCollateral( address indexed user, - address[] ctokens, + address[] atokens, string[] supplyIds, string[] borrowIds, uint256[] flashLoanFees, diff --git a/contracts/optimism/connectors/aave/v3-import/helpers.sol b/contracts/optimism/connectors/aave/v3-import/helpers.sol index 09620366..710d1880 100644 --- a/contracts/optimism/connectors/aave/v3-import/helpers.sol +++ b/contracts/optimism/connectors/aave/v3-import/helpers.sol @@ -1,9 +1,10 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; import { DSMath } from "../../../common/math.sol"; import { Basic } from "../../../common/basic.sol"; -import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import { TokenInterface, AccountInterface, ListInterface } from "../../../common/interfaces.sol"; import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; import "./events.sol"; import "./interface.sol"; @@ -26,6 +27,12 @@ abstract contract Helper is DSMath, Basic { AaveDataProviderInterface internal constant aaveData = AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); + /** + * @dev InstaList + */ + ListInterface internal constant instaList = + ListInterface(0x839c2D3aDe63DF5b0b8F3E57D5e145057Ab41556); + function getIsColl(address token, address user) internal view @@ -231,20 +238,60 @@ contract AaveHelpers is Helper { address[] memory tokens, address userAccount ) internal { - for (uint256 i = 0; i < _length; i++) { - if (amts[i] > 0) { - uint256 _amt = amts[i]; - require( - atokenContracts[i].transferFrom( - userAccount, - address(this), - _amt - ), - "allowance?" - ); + if (instaList.accountID(userAccount) == 0) { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + atokenContracts[i].transferFrom( + userAccount, + address(this), + _amt + ), + "allowance?" + ); + if (!getIsColl(tokens[i], address(this))) { + aave.setUserUseReserveAsCollateral(tokens[i], true); + } + } + } + } else { + uint256 _len = 0; + uint256 _cntr = 0; + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _len++; + } + } + string[] memory _targets = new string[](_len); + bytes[] memory _data = new bytes[](_len); + address[] memory _tokens = new address[](_len); + bytes4 basicWithdraw = bytes4( + keccak256("withdraw(address,uint256,address,uint256,uint256)") + ); - if (!getIsColl(tokens[i], address(this))) { - aave.setUserUseReserveAsCollateral(tokens[i], true); + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = address(atokenContracts[i]); + _targets[_cntr] = "BASIC-A"; + _data[_cntr] = abi.encodeWithSelector( + basicWithdraw, + _token, + _amt, + address(this), + 0, + 0 + ); + _tokens[_cntr] = tokens[i]; + _cntr++; + } + } + + AccountInterface(userAccount).cast(_targets, _data, address(this)); + for (uint256 i = 0; i < _len; i++) { + if (!getIsColl(_tokens[i], address(this))) { + aave.setUserUseReserveAsCollateral(_tokens[i], true); } } } @@ -259,20 +306,67 @@ contract AaveHelpers is Helper { bool[] memory colEnable, address userAccount ) internal { - for (uint256 i = 0; i < _length; i++) { - if (amts[i] > 0) { - uint256 _amt = amts[i]; - require( - atokenContracts[i].transferFrom( - userAccount, - address(this), - _amt - ), - "allowance?" - ); + if (instaList.accountID(userAccount) == 0) { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + atokenContracts[i].transferFrom( + userAccount, + address(this), + _amt + ), + "allowance?" + ); - if (!getIsColl(tokens[i], address(this))) { - aave.setUserUseReserveAsCollateral(tokens[i], colEnable[i]); + if (!getIsColl(tokens[i], address(this))) { + aave.setUserUseReserveAsCollateral( + tokens[i], + colEnable[i] + ); + } + } + } + } else { + uint256 _len = 0; + uint256 _cntr = 0; + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _len++; + } + } + string[] memory _targets = new string[](_len); + bytes[] memory _data = new bytes[](_len); + address[] memory _tokens = new address[](_len); + bytes4 basicWithdraw = bytes4( + keccak256("withdraw(address,uint256,address,uint256,uint256)") + ); + + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = address(atokenContracts[i]); + _targets[_cntr] = "BASIC-A"; + _data[_cntr] = abi.encodeWithSelector( + basicWithdraw, + _token, + _amt, + address(this), + 0, + 0 + ); + _tokens[_cntr] = tokens[i]; + _cntr++; + } + } + + AccountInterface(userAccount).cast(_targets, _data, address(this)); + for (uint256 i = 0; i < _len; i++) { + if (!getIsColl(_tokens[i], address(this))) { + aave.setUserUseReserveAsCollateral( + _tokens[i], + colEnable[i] + ); } } } diff --git a/contracts/optimism/connectors/aave/v3-import/main.sol b/contracts/optimism/connectors/aave/v3-import/main.sol index 6b9acfb1..3fd7fe7f 100644 --- a/contracts/optimism/connectors/aave/v3-import/main.sol +++ b/contracts/optimism/connectors/aave/v3-import/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** * @title Aave v3 import connector . - * @dev Import EOA's aave V3 position to DSA's aave v3 position + * Import EOA's / External DSA's aave V3 position to DSA's aave v3 position */ import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; import { AaveInterface, ATokenInterface } from "./interface.sol"; @@ -15,10 +15,17 @@ contract AaveV3ImportResolver is AaveHelpers { internal returns (string memory _eventName, bytes memory _eventParam) { - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); + if (instaList.accountID(userAccount) == 0) { + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + } else { + require( + AccountInterface(userAccount).isAuth(address(this)), + "user-account-not-auth" + ); + } require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); @@ -91,18 +98,29 @@ contract AaveV3ImportResolver is AaveHelpers { ); } - function _importAaveWithCollateral(address userAccount, ImportInputData memory inputData, bool[] memory enableCollateral) - internal - returns (string memory _eventName, bytes memory _eventParam) - { - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); + function _importAaveWithCollateral( + address userAccount, + ImportInputData memory inputData, + bool[] memory enableCollateral + ) internal returns (string memory _eventName, bytes memory _eventParam) { + if (instaList.accountID(userAccount) == 0) { + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + } else { + require( + AccountInterface(userAccount).isAuth(address(this)), + "user-account-not-auth" + ); + } require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); - require(enableCollateral.length == inputData.supplyTokens.length, "lengths-not-same"); - + require( + enableCollateral.length == inputData.supplyTokens.length, + "lengths-not-same" + ); + ImportData memory data; AaveInterface aave = AaveInterface(aaveProvider.getPool()); @@ -177,7 +195,7 @@ contract AaveV3ImportResolver is AaveHelpers { /** * @dev Import aave V3 position . * @notice Import EOA's aave V3 position to DSA's aave v3 position - * @param userAccount The address of the EOA from which aave position will be imported + * @param userAccount The address of the EOA from which Aave position will be imported or the address of the DSA to which the DSA's Aave position will be merged * @param inputData The struct containing all the neccessary input data */ function importAave(address userAccount, ImportInputData memory inputData) @@ -191,19 +209,27 @@ contract AaveV3ImportResolver is AaveHelpers { /** * @dev Import aave V3 position (with collateral). * @notice Import EOA's aave V3 position to DSA's aave v3 position - * @param userAccount The address of the EOA from which aave position will be imported + * @param userAccount The address of the EOA from which aave position will be imported or the address of the DSA to which the DSA's Aave position will be merged * @param inputData The struct containing all the neccessary input data * @param enableCollateral The boolean array to enable selected collaterals in the imported position */ - function importAaveWithCollateral(address userAccount, ImportInputData memory inputData, bool[] memory enableCollateral) + function importAaveWithCollateral( + address userAccount, + ImportInputData memory inputData, + bool[] memory enableCollateral + ) external payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAaveWithCollateral(userAccount, inputData, enableCollateral); + (_eventName, _eventParam) = _importAaveWithCollateral( + userAccount, + inputData, + enableCollateral + ); } } contract ConnectV2AaveV3ImportOptimism is AaveV3ImportResolver { - string public constant name = "Aave-v3-import-v1.1"; + string public constant name = "Aave-v3-import-v1.2"; } diff --git a/contracts/polygon/connectors/aave/v3-import/main.sol b/contracts/polygon/connectors/aave/v3-import/main.sol index ff56eec9..0c6f1033 100644 --- a/contracts/polygon/connectors/aave/v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v3-import/main.sol @@ -6,7 +6,7 @@ pragma experimental ABIEncoderV2; * @dev Import EOA's / External DSA's aave V3 position to DSA's aave v3 position */ -import { TokenInterface, AccountInterface, ListInterface } from "../../../common/interfaces.sol"; +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; import { AaveInterface, ATokenInterface } from "./interface.sol"; import "./helpers.sol"; import "./events.sol"; @@ -209,7 +209,7 @@ contract AaveV3ImportResolver is AaveHelpers { /** * @dev Import aave V3 position (with collateral). * @notice Import EOA's aave V3 position to DSA's aave v3 position - * @param userAccount The address of the EOA from which aave position will be imported + * @param userAccount The address of the EOA from which aave position will be imported or the address of the DSA to which the DSA's Aave position will be merged * @param inputData The struct containing all the neccessary input data * @param enableCollateral The boolean array to enable selected collaterals in the imported position */