pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; import { Variables } from "./variables.sol"; /** * @title InstaAccountV2. * @dev DeFi Smart Account Wallet. */ interface ConnectorsInterface { function isConnectors(string[] calldata connectorNames) external view returns (bool, address[] memory); } contract Constants is Variables { // InstaIndex Address. address internal constant instaIndex = 0x2971AdFa57b20E5a416aE5a708A8655A9c74f723; // Migration contract Address. address internal constant migrationContract = address(0); // TODO: update address on deployment // Connnectors Address. address public immutable connectorsM1; constructor(address _connectors) { connectorsM1 = _connectors; } } contract InstaImplementationM1 is Constants { constructor(address _connectors) Constants(_connectors) {} function decodeEvent(bytes memory response) internal pure returns (string memory _eventCode, bytes memory _eventParams) { if (response.length > 0) { (_eventCode, _eventParams) = abi.decode(response, (string, bytes)); } } event LogCastMigrate( address indexed origin, address indexed sender, uint256 value, string[] targetsNames, address[] targets, string[] eventNames, bytes[] eventParams ); receive() external payable {} /** * @dev Delegate the calls to Connector. * @param _target Connector address * @param _data CallData of function. */ function spell(address _target, bytes memory _data) internal returns (bytes memory response) { require(_target != address(0), "target-invalid"); assembly { let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) let size := returndatasize() response := mload(0x40) mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) mstore(response, size) returndatacopy(add(response, 0x20), 0, size) switch iszero(succeeded) case 1 { // throw if delegatecall failed returndatacopy(0x00, 0x00, size) revert(0x00, size) } } } /** * @dev This is the main function, Where all the different functions are called * from Smart Account. * @param _targetNames Array of Connector address. * @param _datas Array of Calldata. */ function castMigrate( string[] calldata _targetNames, bytes[] calldata _datas, address _origin ) external payable returns (bytes32) // Dummy return to fix instaIndex buildWithCast function { uint256 _length = _targetNames.length; require(_auth[msg.sender] || msg.sender == instaIndex || msg.sender == migrationContract, "1: permission-denied"); require(_length != 0, "1: length-invalid"); require(_length == _datas.length , "1: array-length-invalid"); string[] memory eventNames = new string[](_length); bytes[] memory eventParams = new bytes[](_length); // TODO: restrict migration contract to run something specific? or give is all access as it doesn't have power to run anything else (bool isOk, address[] memory _targets) = ConnectorsInterface(connectorsM1).isConnectors(_targetNames); require(isOk, "1: not-connector"); for (uint i = 0; i < _length; i++) { bytes memory response = spell(_targets[i], _datas[i]); (eventNames[i], eventParams[i]) = decodeEvent(response); } emit LogCastMigrate( _origin, msg.sender, msg.value, _targetNames, _targets, eventNames, eventParams ); } }