ETH Price: $2,383.39 (-5.01%)

Transaction Decoder

Block:
12872310 at Jul-21-2021 09:53:10 PM +UTC
Transaction Fee:
0.001648922 ETH $3.93
Gas Used:
74,951 Gas / 22 Gwei

Emitted Events:

91 InstaAccountV2.0xf6d9b29bbf2ae698de33670961ec53f895af65801d2cdaced431cc6129865347( 0xf6d9b29bbf2ae698de33670961ec53f895af65801d2cdaced431cc6129865347, 0x00000000000000000000000003d70891b8994feb6cca7022b25c32be92ee3725, 0x000000000000000000000000585647ac6b0f249aab69c6dba940c344ce1dac50, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000000a0, 0000000000000000000000000000000000000000000000000000000000000120, 0000000000000000000000000000000000000000000000000000000000000160, 0000000000000000000000000000000000000000000000000000000000000200, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000007, 42415349432d4100000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000009926955e0dd681dc303370c52f4ad0a4dd061687, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000034, 4c6f67576974686472617728616464726573732c75696e743235362c61646472, 6573732c75696e743235362c75696e7432353629000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000a0, 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, 000000000000000000000000000000000000000000000008affd633d79b17141, 000000000000000000000000585647ac6b0f249aab69c6dba940c344ce1dac50, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x585647Ac...4cE1DAC50
11.507056366726541242 Eth
Nonce: 608
171.760761275833965819 Eth
Nonce: 609
160.253704909107424577
0x8379cE98...E0C223348 160.255353831107424577 Eth0 Eth160.255353831107424577
(Ethermine)
2,210.989843250306265365 Eth2,210.991492172306265365 Eth0.001648922

Execution Trace

InstaAccountV2.9304c934( )
  • InstaAccountV2.9304c934( )
    • InstaImplementations.getImplementation( _sig=System.Byte[] ) => ( 0x8a3462A50e1a9Fe8c9e7d9023CAcbD9a98D90021 )
    • InstaImplementationM1.cast( _targetNames=[BASIC-A], _datas=[S9OrggAAAAAAAAAAAAAAAO7u7u7u7u7u7u7u7u7u7u7u7u7u//////////////////////////////////////////8AAAAAAAAAAAAAAABYVkesaw8kmqtpxtupQMNEzh2sUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=], _origin=0x03d70891b8994feB6ccA7022B25c32be92ee3725 ) => ( 0000000000000000000000000000000000000000000000000000000000000000 )
      • InstaConnectorsV2.isConnectors( _connectorNames=[BASIC-A] ) => ( isOk=True, _connectors=[0x9926955e0Dd681Dc303370C52f4Ad0a4dd061687] )
      • ConnectV2Basic.withdraw( token=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, amt=115792089237316195423570985008687907853269984665640564039457584007913129639935, to=0x585647Ac6B0f249Aab69C6dba940c344cE1DAC50, getId=0, setId=0 ) => ( _eventName=LogWithdraw(address,uint256,address,uint256,uint256), _eventParam=0x000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000008AFFD633D79B17141000000000000000000000000585647AC6B0F249AAB69C6DBA940C344CE1DAC5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 )
        • ETH 160.255353831107424577 0x585647ac6b0f249aab69c6dba940c344ce1dac50.CALL( )
          File 1 of 6: InstaAccountV2
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AccountImplementations {
              function getImplementation(bytes4 _sig) external view returns (address);
          }
          /**
           * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
           * instruction `delegatecall`.
           */
          contract InstaAccountV2 {
              AccountImplementations public immutable implementations;
              constructor(address _implementations) {
                  implementations = AccountImplementations(_implementations);
              }
              /**
               * @dev Delegates the current call to `implementation`.
               * 
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _delegate(address implementation) internal {
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      // Copy msg.data. We take full control of memory in this inline assembly
                      // block because it will not return to Solidity code. We overwrite the
                      // Solidity scratch pad at memory position 0.
                      calldatacopy(0, 0, calldatasize())
                      // Call the implementation.
                      // out and outsize are 0 because we don't know the size yet.
                      let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                      // Copy the returned data.
                      returndatacopy(0, 0, returndatasize())
                      switch result
                      // delegatecall returns 0 on error.
                      case 0 { revert(0, returndatasize()) }
                      default { return(0, returndatasize()) }
                  }
              }
              /**
               * @dev Delegates the current call to the address returned by Implementations registry.
               * 
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _fallback(bytes4 _sig) internal {
                  address _implementation = implementations.getImplementation(_sig);
                  require(_implementation != address(0), "InstaAccountV2: Not able to find _implementation");
                  _delegate(_implementation);
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by Implementations registry.
               */
              fallback () external payable {
                  _fallback(msg.sig);
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by Implementations registry.
               */
              receive () external payable {
                  if (msg.sig != 0x00000000) {
                      _fallback(msg.sig);
                  }
              }
          }
          

          File 2 of 6: InstaAccountV2
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AccountImplementations {
              function getImplementation(bytes4 _sig) external view returns (address);
          }
          /**
           * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
           * instruction `delegatecall`.
           */
          contract InstaAccountV2 {
              AccountImplementations public immutable implementations;
              constructor(address _implementations) {
                  implementations = AccountImplementations(_implementations);
              }
              /**
               * @dev Delegates the current call to `implementation`.
               * 
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _delegate(address implementation) internal {
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      // Copy msg.data. We take full control of memory in this inline assembly
                      // block because it will not return to Solidity code. We overwrite the
                      // Solidity scratch pad at memory position 0.
                      calldatacopy(0, 0, calldatasize())
                      // Call the implementation.
                      // out and outsize are 0 because we don't know the size yet.
                      let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                      // Copy the returned data.
                      returndatacopy(0, 0, returndatasize())
                      switch result
                      // delegatecall returns 0 on error.
                      case 0 { revert(0, returndatasize()) }
                      default { return(0, returndatasize()) }
                  }
              }
              /**
               * @dev Delegates the current call to the address returned by Implementations registry.
               * 
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _fallback(bytes4 _sig) internal {
                  address _implementation = implementations.getImplementation(_sig);
                  require(_implementation != address(0), "InstaAccountV2: Not able to find _implementation");
                  _delegate(_implementation);
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by Implementations registry.
               */
              fallback () external payable {
                  _fallback(msg.sig);
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by Implementations registry.
               */
              receive () external payable {
                  if (msg.sig != 0x00000000) {
                      _fallback(msg.sig);
                  }
              }
          }
          

          File 3 of 6: InstaImplementations
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface IndexInterface {
              function master() external view returns (address);
          }
          contract Setup {
              address public defaultImplementation;
              mapping (bytes4 => address) internal sigImplementations;
              mapping (address => bytes4[]) internal implementationSigs;
          }
          contract Implementations is Setup {
              event LogSetDefaultImplementation(address indexed oldImplementation, address indexed newImplementation);
              event LogAddImplementation(address indexed implementation, bytes4[] sigs);
              event LogRemoveImplementation(address indexed implementation, bytes4[] sigs);
              IndexInterface constant public instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
              modifier isMaster() {
                  require(msg.sender == instaIndex.master(), "Implementations: not-master");
                  _;
              }
              function setDefaultImplementation(address _defaultImplementation) external isMaster {
                  require(_defaultImplementation != address(0), "Implementations: _defaultImplementation address not valid");
                  require(_defaultImplementation != defaultImplementation, "Implementations: _defaultImplementation cannot be same");
                  emit LogSetDefaultImplementation(defaultImplementation, _defaultImplementation);
                  defaultImplementation = _defaultImplementation;
              }
              function addImplementation(address _implementation, bytes4[] calldata _sigs) external isMaster {
                  require(_implementation != address(0), "Implementations: _implementation not valid.");
                  require(implementationSigs[_implementation].length == 0, "Implementations: _implementation already added.");
                  for (uint i = 0; i < _sigs.length; i++) {
                      bytes4 _sig = _sigs[i];
                      require(sigImplementations[_sig] == address(0), "Implementations: _sig already added");
                      sigImplementations[_sig] = _implementation;
                  }
                  implementationSigs[_implementation] = _sigs;
                  emit LogAddImplementation(_implementation, _sigs);
              }
              function removeImplementation(address _implementation) external isMaster {
                  require(_implementation != address(0), "Implementations: _implementation not valid.");
                  require(implementationSigs[_implementation].length != 0, "Implementations: _implementation not found.");
                  bytes4[] memory sigs = implementationSigs[_implementation];
                  for (uint i = 0; i < sigs.length; i++) {
                      bytes4 sig = sigs[i];
                      delete sigImplementations[sig];
                  }
                  delete implementationSigs[_implementation];
                  emit LogRemoveImplementation(_implementation, sigs);
              }
          }
          contract InstaImplementations is Implementations {
              function getImplementation(bytes4 _sig) external view returns (address) {
                  address _implementation = sigImplementations[_sig];
                  return _implementation == address(0) ? defaultImplementation : _implementation;
              }
              function getImplementationSigs(address _impl) external view returns (bytes4[] memory) {
                  return implementationSigs[_impl];
              }
              function getSigImplementation(bytes4 _sig) external view returns (address) {
                  return sigImplementations[_sig];
              }
          }
          

          File 4 of 6: InstaImplementationM1
          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 immutable instaIndex;
              // Connectors Address.
              address public immutable connectorsM1;
              constructor(address _instaIndex, address _connectors) {
                  connectorsM1 = _connectors;
                  instaIndex = _instaIndex;
              }
          }
          contract InstaImplementationM1 is Constants {
              constructor(address _instaIndex, address _connectors) Constants(_instaIndex, _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 LogCast(
                  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 cast(
                  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, "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);
                  (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 LogCast(
                      _origin,
                      msg.sender,
                      msg.value,
                      _targetNames,
                      _targets,
                      eventNames,
                      eventParams
                  );
              }
          }pragma solidity ^0.7.0;
          contract Variables {
              // Auth Module(Address of Auth => bool).
              mapping (address => bool) internal _auth;
          }

          File 5 of 6: InstaConnectorsV2
          pragma solidity ^0.7.0;
          pragma experimental ABIEncoderV2;
          /**
           * @title InstaConnectorsV2
           * @dev Registry for Connectors.
           */
          interface IndexInterface {
              function master() external view returns (address);
          }
          interface ConnectorInterface {
              function name() external view returns (string memory);
          }
          contract Controllers {
              event LogController(address indexed addr, bool indexed isChief);
              // InstaIndex Address.
              address public immutable instaIndex;
              constructor(address _instaIndex) {
                  instaIndex = _instaIndex;
              }
              // Enabled Chief(Address of Chief => bool).
              mapping(address => bool) public chief;
              // Enabled Connectors(Connector name => address).
              mapping(string => address) public connectors;
              /**
              * @dev Throws if the sender not is Master Address from InstaIndex
              * or Enabled Chief.
              */
              modifier isChief {
                  require(chief[msg.sender] || msg.sender == IndexInterface(instaIndex).master(), "not-an-chief");
                  _;
              }
              /**
               * @dev Toggle a Chief. Enable if disable & vice versa
               * @param _chiefAddress Chief Address.
              */
              function toggleChief(address _chiefAddress) external {
                  require(msg.sender == IndexInterface(instaIndex).master(), "toggleChief: not-master");
                  chief[_chiefAddress] = !chief[_chiefAddress];
                  emit LogController(_chiefAddress, chief[_chiefAddress]);
              }
          }
          contract InstaConnectorsV2 is Controllers {
              event LogConnectorAdded(
                  bytes32 indexed connectorNameHash,
                  string connectorName,
                  address indexed connector
              );
              event LogConnectorUpdated(
                  bytes32 indexed connectorNameHash,
                  string connectorName,
                  address indexed oldConnector,
                  address indexed newConnector
              );
              event LogConnectorRemoved(
                  bytes32 indexed connectorNameHash,
                  string connectorName,
                  address indexed connector
              );
              constructor(address _instaIndex) public Controllers(_instaIndex) {}
              /**
               * @dev Add Connectors
               * @param _connectorNames Array of Connector Names.
               * @param _connectors Array of Connector Address.
              */
              function addConnectors(string[] calldata _connectorNames, address[] calldata _connectors) external isChief {
                  require(_connectors.length == _connectors.length, "addConnectors: not same length");
                  for (uint i = 0; i < _connectors.length; i++) {
                      require(connectors[_connectorNames[i]] == address(0), "addConnectors: _connectorName added already");
                      require(_connectors[i] != address(0), "addConnectors: _connectors address not vaild");
                      ConnectorInterface(_connectors[i]).name(); // Checking if connector has function name()
                      connectors[_connectorNames[i]] = _connectors[i];
                      emit LogConnectorAdded(keccak256(abi.encodePacked(_connectorNames[i])), _connectorNames[i], _connectors[i]);
                  }
              }
              /**
               * @dev Update Connectors
               * @param _connectorNames Array of Connector Names.
               * @param _connectors Array of Connector Address.
              */
              function updateConnectors(string[] calldata _connectorNames, address[] calldata _connectors) external isChief {
                  require(_connectorNames.length == _connectors.length, "updateConnectors: not same length");
                  for (uint i = 0; i < _connectors.length; i++) {
                      require(connectors[_connectorNames[i]] != address(0), "updateConnectors: _connectorName not added to update");
                      require(_connectors[i] != address(0), "updateConnectors: _connector address is not vaild");
                      ConnectorInterface(_connectors[i]).name(); // Checking if connector has function name()
                      emit LogConnectorUpdated(keccak256(abi.encodePacked(_connectorNames[i])), _connectorNames[i], connectors[_connectorNames[i]], _connectors[i]);
                      connectors[_connectorNames[i]] = _connectors[i];
                  }
              }
              /**
               * @dev Remove Connectors
               * @param _connectorNames Array of Connector Names.
              */
              function removeConnectors(string[] calldata _connectorNames) external isChief {
                  for (uint i = 0; i < _connectorNames.length; i++) {
                      require(connectors[_connectorNames[i]] != address(0), "removeConnectors: _connectorName not added to update");
                      emit LogConnectorRemoved(keccak256(abi.encodePacked(_connectorNames[i])), _connectorNames[i], connectors[_connectorNames[i]]);
                      delete connectors[_connectorNames[i]];
                  }
              }
              /**
               * @dev Check if Connector addresses are enabled.
               * @param _connectors Array of Connector Names.
              */
              function isConnectors(string[] calldata _connectorNames) external view returns (bool isOk, address[] memory _connectors) {
                  isOk = true;
                  uint len = _connectorNames.length;
                  _connectors = new address[](len);
                  for (uint i = 0; i < _connectors.length; i++) {
                      _connectors[i] = connectors[_connectorNames[i]];
                      if (_connectors[i] == address(0)) {
                          isOk = false;
                          break;
                      }
                  }
              }
          }

          File 6 of 6: ConnectV2Basic
          pragma solidity ^0.7.0;
          import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
          import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
          import { DSMath } from "../../common/math.sol";
          import { Basic } from "../../common/basic.sol";
          import { Events } from "./events.sol";
          abstract contract BasicResolver is Events, DSMath, Basic {
              using SafeERC20 for IERC20;
              /**
               * @dev Deposit Assets To Smart Account.
               * @param token Token Address.
               * @param amt Token Amount.
               * @param getId Get Storage ID.
               * @param setId Set Storage ID.
               */
              function deposit(
                  address token,
                  uint256 amt,
                  uint256 getId,
                  uint256 setId
              ) public payable returns (string memory _eventName, bytes memory _eventParam) {
                  uint _amt = getUint(getId, amt);
                  if (token != ethAddr) {
                      IERC20 tokenContract = IERC20(token);
                      _amt = _amt == uint(-1) ? tokenContract.balanceOf(msg.sender) : _amt;
                      tokenContract.safeTransferFrom(msg.sender, address(this), _amt);
                  } else {
                      require(msg.value == _amt || _amt == uint(-1), "invalid-ether-amount");
                      _amt = msg.value;
                  }
                  setUint(setId, _amt);
                  _eventName = "LogDeposit(address,uint256,uint256,uint256)";
                  _eventParam = abi.encode(token, _amt, getId, setId);
              }
              /**
               * @dev Withdraw Assets To Smart Account.
               * @param token Token Address.
               * @param amt Token Amount.
               * @param to Withdraw token address.
               * @param getId Get Storage ID.
               * @param setId Set Storage ID.
               */
              function withdraw(
                  address token,
                  uint amt,
                  address payable to,
                  uint getId,
                  uint setId
              ) public payable returns (string memory _eventName, bytes memory _eventParam) {
                  uint _amt = getUint(getId, amt);
                  if (token == ethAddr) {
                      _amt = _amt == uint(-1) ? address(this).balance : _amt;
                      to.call{value: _amt}("");
                  } else {
                      IERC20 tokenContract = IERC20(token);
                      _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
                      tokenContract.safeTransfer(to, _amt);
                  }
                  setUint(setId, _amt);
                  _eventName = "LogWithdraw(address,uint256,address,uint256,uint256)";
                  _eventParam = abi.encode(token, _amt, to, getId, setId);
              }
          }
          contract ConnectV2Basic is BasicResolver {
              string constant public name = "Basic-v1";
          }
          // SPDX-License-Identifier: MIT
          pragma solidity >=0.6.0 <0.8.0;
          import "./IERC20.sol";
          import "../../math/SafeMath.sol";
          import "../../utils/Address.sol";
          /**
           * @title SafeERC20
           * @dev Wrappers around ERC20 operations that throw on failure (when the token
           * contract returns false). Tokens that return no value (and instead revert or
           * throw on failure) are also supported, non-reverting calls are assumed to be
           * successful.
           * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
           * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
           */
          library SafeERC20 {
              using SafeMath for uint256;
              using Address for address;
              function safeTransfer(IERC20 token, address to, uint256 value) internal {
                  _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
              }
              function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                  _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
              }
              /**
               * @dev Deprecated. This function has issues similar to the ones found in
               * {IERC20-approve}, and its usage is discouraged.
               *
               * Whenever possible, use {safeIncreaseAllowance} and
               * {safeDecreaseAllowance} instead.
               */
              function safeApprove(IERC20 token, address spender, uint256 value) internal {
                  // safeApprove should only be called when setting an initial allowance,
                  // or when resetting it to zero. To increase and decrease it, use
                  // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                  // solhint-disable-next-line max-line-length
                  require((value == 0) || (token.allowance(address(this), spender) == 0),
                      "SafeERC20: approve from non-zero to non-zero allowance"
                  );
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
              }
              function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                  uint256 newAllowance = token.allowance(address(this), spender).add(value);
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
              }
              function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                  uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
              }
              /**
               * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
               * on the return value: the return value is optional (but if data is returned, it must not be false).
               * @param token The token targeted by the call.
               * @param data The call data (encoded using abi.encode or one of its variants).
               */
              function _callOptionalReturn(IERC20 token, bytes memory data) private {
                  // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                  // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
                  // the target address contains contract code and also asserts for success in the low-level call.
                  bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                  if (returndata.length > 0) { // Return data is optional
                      // solhint-disable-next-line max-line-length
                      require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity >=0.6.0 <0.8.0;
          /**
           * @dev Interface of the ERC20 standard as defined in the EIP.
           */
          interface IERC20 {
              /**
               * @dev Returns the amount of tokens in existence.
               */
              function totalSupply() external view returns (uint256);
              /**
               * @dev Returns the amount of tokens owned by `account`.
               */
              function balanceOf(address account) external view returns (uint256);
              /**
               * @dev Moves `amount` tokens from the caller's account to `recipient`.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transfer(address recipient, uint256 amount) external returns (bool);
              /**
               * @dev Returns the remaining number of tokens that `spender` will be
               * allowed to spend on behalf of `owner` through {transferFrom}. This is
               * zero by default.
               *
               * This value changes when {approve} or {transferFrom} are called.
               */
              function allowance(address owner, address spender) external view returns (uint256);
              /**
               * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * IMPORTANT: Beware that changing an allowance with this method brings the risk
               * that someone may use both the old and the new allowance by unfortunate
               * transaction ordering. One possible solution to mitigate this race
               * condition is to first reduce the spender's allowance to 0 and set the
               * desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               *
               * Emits an {Approval} event.
               */
              function approve(address spender, uint256 amount) external returns (bool);
              /**
               * @dev Moves `amount` tokens from `sender` to `recipient` using the
               * allowance mechanism. `amount` is then deducted from the caller's
               * allowance.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
              /**
               * @dev Emitted when `value` tokens are moved from one account (`from`) to
               * another (`to`).
               *
               * Note that `value` may be zero.
               */
              event Transfer(address indexed from, address indexed to, uint256 value);
              /**
               * @dev Emitted when the allowance of a `spender` for an `owner` is set by
               * a call to {approve}. `value` is the new allowance.
               */
              event Approval(address indexed owner, address indexed spender, uint256 value);
          }
          pragma solidity ^0.7.0;
          import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
          contract DSMath {
            uint constant WAD = 10 ** 18;
            uint constant RAY = 10 ** 27;
            function add(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.add(x, y);
            }
            function sub(uint x, uint y) internal virtual pure returns (uint z) {
              z = SafeMath.sub(x, y);
            }
            function mul(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.mul(x, y);
            }
            function div(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.div(x, y);
            }
            function wmul(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.add(SafeMath.mul(x, y), WAD / 2) / WAD;
            }
            function wdiv(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.add(SafeMath.mul(x, WAD), y / 2) / y;
            }
            function rdiv(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.add(SafeMath.mul(x, RAY), y / 2) / y;
            }
            function rmul(uint x, uint y) internal pure returns (uint z) {
              z = SafeMath.add(SafeMath.mul(x, y), RAY / 2) / RAY;
            }
            function toInt(uint x) internal pure returns (int y) {
              y = int(x);
              require(y >= 0, "int-overflow");
            }
            function toRad(uint wad) internal pure returns (uint rad) {
              rad = mul(wad, 10 ** 27);
            }
          }
          pragma solidity ^0.7.0;
          import { TokenInterface } from "./interfaces.sol";
          import { Stores } from "./stores.sol";
          import { DSMath } from "./math.sol";
          abstract contract Basic is DSMath, Stores {
              function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
                  amt = (_amt / 10 ** (18 - _dec));
              }
              function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
                  amt = mul(_amt, 10 ** (18 - _dec));
              }
              function getTokenBal(TokenInterface token) internal view returns(uint _amt) {
                  _amt = address(token) == ethAddr ? address(this).balance : token.balanceOf(address(this));
              }
              function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) {
                  buyDec = address(buyAddr) == ethAddr ?  18 : buyAddr.decimals();
                  sellDec = address(sellAddr) == ethAddr ?  18 : sellAddr.decimals();
              }
              function encodeEvent(string memory eventName, bytes memory eventParam) internal pure returns (bytes memory) {
                  return abi.encode(eventName, eventParam);
              }
              function changeEthAddress(address buy, address sell) internal pure returns(TokenInterface _buy, TokenInterface _sell){
                  _buy = buy == ethAddr ? TokenInterface(wethAddr) : TokenInterface(buy);
                  _sell = sell == ethAddr ? TokenInterface(wethAddr) : TokenInterface(sell);
              }
              function convertEthToWeth(bool isEth, TokenInterface token, uint amount) internal {
                  if(isEth) token.deposit{value: amount}();
              }
              function convertWethToEth(bool isEth, TokenInterface token, uint amount) internal {
                 if(isEth) {
                      token.approve(address(token), amount);
                      token.withdraw(amount);
                  }
              }
          }
          pragma solidity ^0.7.0;
          contract Events {
              event LogDeposit(address indexed erc20, uint256 tokenAmt, uint256 getId, uint256 setId);
              event LogWithdraw(address indexed erc20, uint256 tokenAmt, address indexed to, uint256 getId, uint256 setId);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity >=0.6.0 <0.8.0;
          /**
           * @dev Wrappers over Solidity's arithmetic operations with added overflow
           * checks.
           *
           * Arithmetic operations in Solidity wrap on overflow. This can easily result
           * in bugs, because programmers usually assume that an overflow raises an
           * error, which is the standard behavior in high level programming languages.
           * `SafeMath` restores this intuition by reverting the transaction when an
           * operation overflows.
           *
           * Using this library instead of the unchecked operations eliminates an entire
           * class of bugs, so it's recommended to use it always.
           */
          library SafeMath {
              /**
               * @dev Returns the addition of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
              /**
               * @dev Returns the substraction of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
              /**
               * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
              /**
               * @dev Returns the division of two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
              /**
               * @dev Returns the addition of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               *
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, "SafeMath: addition overflow");
                  return c;
              }
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on
               * overflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a, "SafeMath: subtraction overflow");
                  return a - b;
              }
              /**
               * @dev Returns the multiplication of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               *
               * - Multiplication cannot overflow.
               */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  if (a == 0) return 0;
                  uint256 c = a * b;
                  require(c / a == b, "SafeMath: multiplication overflow");
                  return c;
              }
              /**
               * @dev Returns the integer division of two unsigned integers, reverting on
               * division by zero. The result is rounded towards zero.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: division by zero");
                  return a / b;
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting when dividing by zero.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: modulo by zero");
                  return a % b;
              }
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
               * overflow (when the result is negative).
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {trySub}.
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b <= a, errorMessage);
                  return a - b;
              }
              /**
               * @dev Returns the integer division of two unsigned integers, reverting with custom message on
               * division by zero. The result is rounded towards zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryDiv}.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a / b;
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting with custom message when dividing by zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryMod}.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity >=0.6.2 <0.8.0;
          /**
           * @dev Collection of functions related to the address type
           */
          library Address {
              /**
               * @dev Returns true if `account` is a contract.
               *
               * [IMPORTANT]
               * ====
               * It is unsafe to assume that an address for which this function returns
               * false is an externally-owned account (EOA) and not a contract.
               *
               * Among others, `isContract` will return false for the following
               * types of addresses:
               *
               *  - an externally-owned account
               *  - a contract in construction
               *  - an address where a contract will be created
               *  - an address where a contract lived, but was destroyed
               * ====
               */
              function isContract(address account) internal view returns (bool) {
                  // This method relies on extcodesize, which returns 0 for contracts in
                  // construction, since the code is only stored at the end of the
                  // constructor execution.
                  uint256 size;
                  // solhint-disable-next-line no-inline-assembly
                  assembly { size := extcodesize(account) }
                  return size > 0;
              }
              /**
               * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
               * `recipient`, forwarding all available gas and reverting on errors.
               *
               * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
               * of certain opcodes, possibly making contracts go over the 2300 gas limit
               * imposed by `transfer`, making them unable to receive funds via
               * `transfer`. {sendValue} removes this limitation.
               *
               * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
               *
               * IMPORTANT: because control is transferred to `recipient`, care must be
               * taken to not create reentrancy vulnerabilities. Consider using
               * {ReentrancyGuard} or the
               * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
               */
              function sendValue(address payable recipient, uint256 amount) internal {
                  require(address(this).balance >= amount, "Address: insufficient balance");
                  // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                  (bool success, ) = recipient.call{ value: amount }("");
                  require(success, "Address: unable to send value, recipient may have reverted");
              }
              /**
               * @dev Performs a Solidity function call using a low level `call`. A
               * plain`call` is an unsafe replacement for a function call: use this
               * function instead.
               *
               * If `target` reverts with a revert reason, it is bubbled up by this
               * function (like regular Solidity function calls).
               *
               * Returns the raw returned data. To convert to the expected return value,
               * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
               *
               * Requirements:
               *
               * - `target` must be a contract.
               * - calling `target` with `data` must not revert.
               *
               * _Available since v3.1._
               */
              function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                return functionCall(target, data, "Address: low-level call failed");
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
               * `errorMessage` as a fallback revert reason when `target` reverts.
               *
               * _Available since v3.1._
               */
              function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                  return functionCallWithValue(target, data, 0, errorMessage);
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
               * but also transferring `value` wei to `target`.
               *
               * Requirements:
               *
               * - the calling contract must have an ETH balance of at least `value`.
               * - the called Solidity function must be `payable`.
               *
               * _Available since v3.1._
               */
              function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                  return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
              }
              /**
               * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
               * with `errorMessage` as a fallback revert reason when `target` reverts.
               *
               * _Available since v3.1._
               */
              function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                  require(address(this).balance >= value, "Address: insufficient balance for call");
                  require(isContract(target), "Address: call to non-contract");
                  // solhint-disable-next-line avoid-low-level-calls
                  (bool success, bytes memory returndata) = target.call{ value: value }(data);
                  return _verifyCallResult(success, returndata, errorMessage);
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
               * but performing a static call.
               *
               * _Available since v3.3._
               */
              function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                  return functionStaticCall(target, data, "Address: low-level static call failed");
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
               * but performing a static call.
               *
               * _Available since v3.3._
               */
              function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                  require(isContract(target), "Address: static call to non-contract");
                  // solhint-disable-next-line avoid-low-level-calls
                  (bool success, bytes memory returndata) = target.staticcall(data);
                  return _verifyCallResult(success, returndata, errorMessage);
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
               * but performing a delegate call.
               *
               * _Available since v3.4._
               */
              function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionDelegateCall(target, data, "Address: low-level delegate call failed");
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
               * but performing a delegate call.
               *
               * _Available since v3.4._
               */
              function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                  require(isContract(target), "Address: delegate call to non-contract");
                  // solhint-disable-next-line avoid-low-level-calls
                  (bool success, bytes memory returndata) = target.delegatecall(data);
                  return _verifyCallResult(success, returndata, errorMessage);
              }
              function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                  if (success) {
                      return returndata;
                  } else {
                      // Look for revert reason and bubble it up if present
                      if (returndata.length > 0) {
                          // The easiest way to bubble the revert reason is using memory via assembly
                          // solhint-disable-next-line no-inline-assembly
                          assembly {
                              let returndata_size := mload(returndata)
                              revert(add(32, returndata), returndata_size)
                          }
                      } else {
                          revert(errorMessage);
                      }
                  }
              }
          }
          pragma solidity ^0.7.0;
          interface TokenInterface {
              function approve(address, uint256) external;
              function transfer(address, uint) external;
              function transferFrom(address, address, uint) external;
              function deposit() external payable;
              function withdraw(uint) external;
              function balanceOf(address) external view returns (uint);
              function decimals() external view returns (uint);
          }
          interface MemoryInterface {
              function getUint(uint id) external returns (uint num);
              function setUint(uint id, uint val) external;
          }
          interface InstaMapping {
              function cTokenMapping(address) external view returns (address);
              function gemJoinMapping(bytes32) external view returns (address);
          }
          interface AccountInterface {
              function enable(address) external;
              function disable(address) external;
              function isAuth(address) external view returns (bool);
          }
          pragma solidity ^0.7.0;
          import { MemoryInterface, InstaMapping } from "./interfaces.sol";
          abstract contract Stores {
            /**
             * @dev Return ethereum address
             */
            address constant internal ethAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
            /**
             * @dev Return Wrapped ETH address
             */
            address constant internal wethAddr = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
            /**
             * @dev Return memory variable address
             */
            MemoryInterface constant internal instaMemory = MemoryInterface(0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F);
            /**
             * @dev Return InstaDApp Mapping Addresses
             */
            InstaMapping constant internal instaMapping = InstaMapping(0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88);
            /**
             * @dev Get Uint value from InstaMemory Contract.
             */
            function getUint(uint getId, uint val) internal returns (uint returnVal) {
              returnVal = getId == 0 ? val : instaMemory.getUint(getId);
            }
            /**
            * @dev Set Uint value in InstaMemory Contract.
            */
            function setUint(uint setId, uint val) virtual internal {
              if (setId != 0) instaMemory.setUint(setId, val);
            }
          }